Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

equivalent of getbuffer for BytesIO in Python 2

In Python 3, I can get the size of a ByteIO object via object.getbuffer().nbytes (where object = ByteIO()), but what would be the best equivalent for getbuffer() in Python 2? Doing some exploring, I found out I can use len(object.getvalue()) or sys.getsizeof(object), but I don't know if Python 2 will accept them.

like image 358
Brian Lee Avatar asked Mar 08 '23 08:03

Brian Lee


2 Answers

see critical update below

After digging in python 2.7 source code I found a simple solution: because io.BytesIO() returns a file descriptor, it has a standard set of functions including tell().

Note that indirect methods such as len(fd.getvalue()) or fd.getbuffer().nbytes copy buffer out and then compute buffer size. In my case, when the buffer holds 1/2 of the memory, this ends up as an application crash :/

Contrary fd.tell() just reports a current position of the descriptor and do not need any memory allocation!

Note that both sys.getsizeof(fd), fd.__sizeof__() do not return correct bufer size.

>>> 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

UPDATE

After @admaster and @Artemis comments I realized that the correct method, in case of preset buffer, is to move the pointer to the end of the buffer. Standard seek function can do that, ant it will report the current buffer size

buffsize = fd.seek(0,2)

So here how it should be done without unnecessary coping memory

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
like image 195
rth Avatar answered Mar 31 '23 12:03

rth


You can use getvalue()

Example:

from io import BytesIO
if __name__ == "__main__":
    out = BytesIO()
    out.write(b"test\0")
    print len(out.getvalue())

See: https://docs.python.org/2/library/io.html#io.BytesIO.getvalue

like image 21
Ale Avatar answered Mar 31 '23 13:03

Ale