4

object.getbuffer().nbytes在 Python 3 中,我可以通过(where )获取 ByteIO 对象的大小,但是在 Python 2 中object = ByteIO()什么是最好的等价物?getbuffer()做了一些探索,我发现我可以使用len(object.getvalue())or sys.getsizeof(object),但我不知道 Python 2 是否会接受它们。

4

3 回答 3

4

请参阅下面的关键更新

在挖掘了 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
于 2019-01-03T22:38:17.520 回答
2

您可以使用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

于 2017-11-14T14:07:33.787 回答
1

值得注意的是,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 对象并将我们的字节字符串写入它,因此文件描述符现在位于流的末尾,因此我们不需要读取它来更新描述符。

于 2020-03-30T15:19:40.430 回答