object.getbuffer().nbytes
在 Python 3 中,我可以通过(where )获取 ByteIO 对象的大小,但是在 Python 2 中object = ByteIO()
什么是最好的等价物?getbuffer()
做了一些探索,我发现我可以使用len(object.getvalue())
or sys.getsizeof(object)
,但我不知道 Python 2 是否会接受它们。
3 回答
请参阅下面的关键更新
在挖掘了 python 2.7 源代码后,我找到了一个简单的解决方案:因为io.BytesIO()
返回一个文件描述符,它有一组标准的函数,包括tell()
.
请注意,间接方法,例如len(fd.getvalue())
或fd.getbuffer().nbytes
将缓冲区复制出来,然后计算缓冲区大小。就我而言,当缓冲区拥有 1/2 的内存时,这最终会导致应用程序崩溃:/
相反fd.tell()
,只报告描述符的当前位置,不需要任何内存分配!
请注意,两者sys.getsizeof(fd)
都fd.__sizeof__()
不会返回正确的缓冲区大小。
>>> from io import BytesIO
>>> from sys import getsizeof
>>> with BytesIO() as fd:
... for x in xrange(200):
... fd.write(" ")
... print fd.tell(), fd.__sizeof__(), getsizeof(fd)
1 66 98
2 66 98
3 68 100
4 68 100
5 70 102
6 70 102
.....
194 265 297
195 265 297
196 265 297
197 265 297
198 265 297
199 265 297
200 265 297
更新
在@admaster 和@Artemis 评论之后,我意识到,在预设缓冲区的情况下,正确的方法是将指针移动到缓冲区的末尾。标准seek
函数可以做到这一点,它会报告当前缓冲区大小
buffsize = fd.seek(0,2)
所以这里应该如何在没有不必要的应对记忆的情况下完成
from io import BytesIO
x = BytesIO(b'AAAAAA')
x.seek(0,2) # returns 6
x.tell() # returns 6
# However
x = BytesIO()
x.write(b'AAAAAA')
x.seek(0,2) # returns 6
x.tell() # returns 6
您可以使用getvalue()
例子:
from io import BytesIO
if __name__ == "__main__":
out = BytesIO()
out.write(b"test\0")
print len(out.getvalue())
请参阅:https ://docs.python.org/2/library/io.html#io.BytesIO.getvalue
值得注意的是,tell() 只会返回文件描述符的当前位置,而不一定是缓冲区的大小。
这可以在以下示例中看到:
from io import BytesIO
x = BytesIO(b'AAAAAA')
x.tell() # returns 0
x.read()
x.tell() # Now it returns 6
# However
x = BytesIO()
x.write(b'AAAAAA')
x.tell() # returns 6
在第一个示例中,我们使用字节字符串初始化了对象,但文件描述符仍在开头,因此返回 0,然后我们读取流,这意味着我们的文件描述符将移动到末尾,结果它返回 6。
在第二个示例中,我们初始化一个空的 BytesIO 对象并将我们的字节字符串写入它,因此文件描述符现在位于流的末尾,因此我们不需要读取它来更新描述符。