В Python 3 я могу получить размер объекта ByteIO через object.getbuffer().nbytes
(где object = ByteIO()
), но что будет лучшим эквивалентом для getbuffer()
в Python 2? Проведя некоторые исследования, я обнаружил, что могу использовать len(object.getvalue())
или sys.getsizeof(object)
, но я не знаю, примет ли их Python 2.
эквивалент getbuffer для BytesIO в 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
tell()
вернет 0 (например, BytesIO(b'00').tell()
), поэтому getvalue()
более надежен.
- person eadmaster; 29.01.2020
tell()
должен сообщать о текущем размере записанных данных, а если данные были заимствованы из другого буфера, он должен сообщать о размере данных в этом буфере.
- person rth; 29.01.2020
tell()
не сообщает о текущем размере записанных данных, а сообщает о текущей позиции указателя. Это будет только текущий размер данных, если указатель в данный момент находится в конце файла.
- person Artemis; 19.02.2021
Вы можете использовать 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 и записываем в него нашу строку байтов, в результате дескриптор файла теперь находится в конце потока, и поэтому нам не нужно его читать для обновления дескриптора.
BytesIO
, это количество байтов базового буфера. Но почему вы просто не пробовали, работает лиlen(object.getvalue())
в Python 2 или нет? - person juanpa.arrivillaga   schedule 14.08.2017getbuffer().nbytes
- person Brian Lee   schedule 14.08.2017io.BytesIO
объектов. - person juanpa.arrivillaga   schedule 14.08.2017sys.getsizeof(object)
не будет не эквивалентным. - person juanpa.arrivillaga   schedule 14.08.2017