Python:如何获得指向字节数组的可变切片?

Python:如何获得指向字节数组的可变切片?,python,python-2.7,io,Python,Python 2.7,Io,我想要一个指向a并且是可变的版本。我想把它传递给I/O函数,就像在循环中没有内存分配的开销一样 import sys, struct ba = bytearray(2000) lenbuf = bytearray(8) with open(sys.argv[1]) as fp: while True: fp.readinto(lenbuf) # efficient version of fp.read(8) dat_len = struct.unpack("Q", le

我想要一个指向a并且是可变的版本。我想把它传递给I/O函数,就像在循环中没有内存分配的开销一样

import sys, struct

ba = bytearray(2000)
lenbuf = bytearray(8)

with open(sys.argv[1]) as fp:
  while True:
    fp.readinto(lenbuf)  # efficient version of fp.read(8)
    dat_len = struct.unpack("Q", lenbuf)
    buf = buffer(ba, 0, dat_len)
    fp.readinto(buf)  # efficient version of fp.read(dat_len), but
                      # yields TypeError: must be read-write buffer, not buffer
    my_parse(buf)
我还尝试了
buf=
(缓冲区(ba,0,长度))
,但(本质上)得到了相同的错误

我相信,使用Python不应该等同于对运行时性能关注不够

默认情况下,我使用安装在Cent6上的Python2.6,但如果确实需要,可以切换到2.7或3.x

谢谢


更新您可以让它读取多余的数据,然后在从文件中读取更多数据之前,简单地使用bytearray中的所有多余数据

否则,您可以使用numpy:

import sys, struct
import numpy as np

buf = np.zeros(2000, dtype=np.uint8)
lenbuf = bytearray(8)

with open(sys.argv[1]) as fp:
    while True:
        fp.readinto(lenbuf)
        dat_len = struct.unpack("Q", lenbuf)
        fp.readinto(buf[:dat_len])
        my_parse(buf[:dat_len])

numpy创建所需的读写缓冲区,索引[:dat_len]返回数据子集的“视图”,而不是副本。由于numpy数组符合缓冲区协议,您可以将它们与struct.unpack()一起使用,就像它们是bytearray/buffers一样。

当您提到的所有函数实际上都需要bytearray时,为什么您需要一个缓冲区?因为这些I/O函数尝试填充
len(buf)
字节,但我希望继续重用单个字节“足够长的”缓冲区(
bytearray(2000)
)我很好奇您的代码和@ALGOholic代码之间是否有任何性能改进。因为坦率地说,对于垃圾收集,试图修复假定的内存分配开销是相当大胆的。”您可以让它读取多余的数据,然后在从文件中读取更多数据之前简单地使用bytearray中的所有多余数据。“对不起,您的意思是我应该在这里自己实现缓冲I/O。但是感谢您让我了解NumPy数组类型。
>>> x = bytearray(4*10**9)
>>> x = bytearray(10)
>>> x[2] = 0xff
>>> x.count(b'\x00')
9
>>> x[3:5][0] = 0xff
>>> x.count(b'\x00')
9  # WHAT
import sys, struct
import numpy as np

buf = np.zeros(2000, dtype=np.uint8)
lenbuf = bytearray(8)

with open(sys.argv[1]) as fp:
    while True:
        fp.readinto(lenbuf)
        dat_len = struct.unpack("Q", lenbuf)
        fp.readinto(buf[:dat_len])
        my_parse(buf[:dat_len])