K.-*_*Aye 7 python stdin numpy stringio
有几个类似的问题,但没有一个直接回答这个简单的问题:
如何捕获命令输出并将该内容流式传输到numpy数组而不创建要读取的临时字符串对象?
那么,我想做的是:
import subprocess
import numpy
import StringIO
def parse_header(fileobject):
# this function moves the filepointer and returns a dictionary
d = do_some_parsing(fileobject)
return d
sio = StringIO.StringIO(subprocess.check_output(cmd))
d = parse_header(sio)
# now the file pointer is at the start of data, parse_header takes care of that.
# ALL of the data is now available in the next line of sio
dt = numpy.dtype([(key, 'f8') for key in d.keys()])
# i don't know how do make this work:
data = numpy.fromxxxx(sio , dt)
# if i would do this, I create another copy besides the StringIO object, don't I?
# so this works, but isn't this 'bad' ?
datastring = sio.read()
data = numpy.fromstring(datastring, dtype=dt)
Run Code Online (Sandbox Code Playgroud)
我尝试使用StringIO和cStringIO,但numpy.frombuffer和numpy.fromfile都不接受它们.
使用StringIO对象我首先要将流读入字符串然后使用numpy.fromstring,但我想避免创建中间对象(几千兆字节).
对我来说,另一种选择是如果我可以将sys.stdin流式传输到numpy数组中,但这对numpy.fromfile也不起作用(seek需要实现).
这有什么解决方法吗?我不能成为第一个尝试这个的人(除非这是一个PEBKAC案例?)
解决方案:这是当前的解决方案,它是unutbu指令的混合,如何使用PIPE的Popen和eryksun使用bytearray的提示,所以我不知道接受谁!?:S
proc = sp.Popen(cmd, stdout = sp.PIPE, shell=True)
d = parse_des_header(proc.stdout)
rec_dtype = np.dtype([(key,'f8') for key in d.keys()])
data = bytearray(proc.stdout.read())
ndata = np.frombuffer(data, dtype = rec_dtype)
Run Code Online (Sandbox Code Playgroud)
我没有检查数据是否真的没有创建另一个副本,不知道如何.但是我注意到这比我之前尝试的所有内容都快得多,所以非常感谢答案的作者!
您可以使用Popen与stdout=subprocess.PIPE。阅读标题,然后将其余部分加载到中bytearray以与一起使用np.frombuffer。
根据您的修改的其他评论:
如果您要拨打电话proc.stdout.read(),则等同于使用check_output()。两者都创建一个临时字符串。如果预分配data,则可以使用proc.stdout.readinto(data)。然后,如果读入的字节数data少于len(data),则释放多余的内存,否则扩展data剩下的要读取的内容。
data = bytearray(2**32) # 4 GiB
n = proc.stdout.readinto(data)
if n < len(data):
data[n:] = ''
else:
data += proc.stdout.read()
Run Code Online (Sandbox Code Playgroud)
您也可以从预先分配ndarray ndata和使用开始buf = np.getbuffer(ndata)。然后readinto(buf)如上所述。
这是一个示例,显示了在bytearray和 之间共享内存np.ndarray:
>>> data = bytearray('\x01')
>>> ndata = np.frombuffer(data, np.int8)
>>> ndata
array([1], dtype=int8)
>>> ndata[0] = 2
>>> data
bytearray(b'\x02')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5382 次 |
| 最近记录: |