Я гуглил и также ищу на SO разницу между этими буферными модулями. Тем не менее, я все еще не очень хорошо понимаю, и я думаю, что некоторые из прочитанных мной постов устарели.
В Python 2.7.11 я загрузил двоичный файл определенного формата, используя r = requests.get(url)
. Затем я передал StringIO.StringIO(r.content)
, cStringIO.StringIO(r.content)
и io.BytesIO(r.content)
в функцию, предназначенную для анализа содержимого.
Все эти три метода доступны. Я имею в виду, даже если файл является двоичным, все еще возможно использовать StringIO
. Зачем?
Другое дело, относительно их эффективности.
In [1]: import StringIO, cStringIO, io
In [2]: from numpy import random
In [3]: x = random.random(1000000)
In [4]: %timeit y = cStringIO.StringIO(x)
1000000 loops, best of 3: 736 ns per loop
In [5]: %timeit y = StringIO.StringIO(x)
1000 loops, best of 3: 283 µs per loop
In [6]: %timeit y = io.BytesIO(x)
1000 loops, best of 3: 1.26 ms per loop
Как показано выше, cStringIO > StringIO > BytesIO
.
Я обнаружил, что кто-то упомянул, что io.BytesIO
всегда делает новую копию, которая стоит больше времени. Но есть также некоторые сообщения, упомянутые, что это было исправлено в более поздних версиях Python.
Так может ли кто-нибудь провести тщательное сравнение этих IO
в последних версиях Python 2.x и 3.x?
Некоторые из ссылок, которые я нашел:
- https://trac.edgewall.org/ticket/12046
io.StringIO требует строку в кодировке Unicode. io.BytesIO требуется строка байтов. StringIO.StringIO допускает либо Unicode, либо байтовую строку. cStringIO.StringIO требует строку, которая закодирована как строка байтов.
Но cStringIO.StringIO('abc')
не вызывает никаких ошибок.
-
https://review.openstack.org/#/c/286926/1
Класс StringIO - это неправильный класс для использования, особенно если учесть, что субъединица v2 является двоичной, а не строкой.
-
http://comments.gmane.org/gmane.comp.python.devel/148717
cStringIO.StringIO(b'data ') не копировал данные, в то время как io.BytesIO(b'data') делает копию (даже если данные не будут изменены позже).
В этом посте есть исправление в 2014 году.
- Много SO сообщений, не перечисленных здесь.
Вот результаты Python 2.7 для примера Эрика
%timeit cStringIO.StringIO(u_data)
1000000 loops, best of 3: 488 ns per loop
%timeit cStringIO.StringIO(b_data)
1000000 loops, best of 3: 448 ns per loop
%timeit StringIO.StringIO(u_data)
1000000 loops, best of 3: 1.15 µs per loop
%timeit StringIO.StringIO(b_data)
1000000 loops, best of 3: 1.19 µs per loop
%timeit io.StringIO(u_data)
1000 loops, best of 3: 304 µs per loop
# %timeit io.StringIO(b_data)
# error
# %timeit io.BytesIO(u_data)
# error
%timeit io.BytesIO(b_data)
10000 loops, best of 3: 77.5 µs per loop
Что касается 2.7, cStringIO.StringIO
и StringIO.StringIO
гораздо более эффективны, чем io
.