2016-05-26 2 views
14

私はグーグルで、これらのバッファモジュールの違いについてもSOを検索しました。しかし、私はまだよく理解していないし、私が読んだいくつかの投稿は時代遅れだと思う。StringIO、cStringIOとByteIOについての混乱

Python 2.7.11では、r = requests.get(url)を使用して特定の形式のバイナリファイルをダウンロードしました。そして、内容を解析するために設計された関数にStringIO.StringIO(r.content),cStringIO.StringIO(r.content)およびio.BytesIO(r.content)を渡しました。

これら3つの方法はすべて利用できます。つまり、ファイルがバイナリであっても、StringIOを使用することはまだ可能です。どうして?

もう1つは効率に関するものです。

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の後のバージョンで修正されたという記事もあります。

だから、誰でも最新のPython 2.xと3.xの両方で、これらの間の完全な比較を行うことができますか。IO


私が見つけた参照の一部

  • https://trac.edgewall.org/ticket/12046

    io.StringIO requires a unicode string. io.BytesIO requires a bytes string. StringIO.StringIO allows either unicode or bytes string. cStringIO.StringIO requires a string that is encoded as a bytes string.

しかし、任意のエラーをcStringIO.StringIO('abc')発生しません。

    で、この記事では修正パッチがあります
  • SOの投稿の多くはここに記載されていません。ここで

エリックの例2.7、cStringIO.StringIOStringIO.StringIOについては

%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 

ためのPython 2.7の結果は、はるかに効率的ioよりもされています。

+0

あなたのスニPython 2またはPython 3としてppets? – Eric

+0

@エリック、私はPython 2.7.11ですべてのテストを行った。私は主に2.7を使用しています。「(c)StringIOは、ioで置き換えられています。しかし、私は、他の読者が両方のバージョンについて議論することが意味があると思います。 – Lee

+1

['io'](https://docs.python.org/2/library/io.html)もPython 2にあります – Eric

答えて

13

転送互換性のために、データがバイナリであるかどうかに応じて、io.StringIOまたはio.BytesIOを使用する必要があります(これはすべて3つ必要です)。で

import io 
%timeit io.StringIO(u_data) 
%timeit io.StringIO(b_data) 
%timeit io.BytesIO(u_data) 
%timeit io.BytesIO(b_data) 

:ここ


はnumpyのからstr/bytes

import numpy as np 
import string 
b_data = np.random.choice(list(string.printable), size=1000000).tobytes() 
u_data = b_data.decode('ascii') 
u_data = u'\u2603' + u_data[1:] # add a non-ascii character 

その後に変換費用が含まれていません(のpython 2と3のための)より良いテスト、ですPython 2、あなたもテストすることができます:

import StringIO, cStringIO 
%timeit cStringIO.StringIO(u_data) 
%timeit cStringIO.StringIO(b_data) 
%timeit StringIO.StringIO(u_data) 
%timeit StringIO.StringIO(b_data) 

これらのいくつかがクラッシュします、Pythonは3.5結果


非ASCII文字不満:

>>> %timeit io.StringIO(u_data) 
100 loops, best of 3: 8.61 ms per loop 
>>> %timeit io.StringIO(b_data) 
TypeError: initial_value must be str or None, not bytes 
>>> %timeit io.BytesIO(u_data) 
TypeError: a bytes-like object is required, not 'str' 
>>> %timeit io.BytesIO(b_data) 
The slowest run took 6.79 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 344 ns per loop 

のPython 2.7の結果(別のマシン上で実行):

>>> %timeit io.StringIO(u_data) 
1000 loops, best of 3: 304 µs per loop 
>>> %timeit io.StringIO(b_data) 
TypeError: initial_value must be unicode or None, not str 
>>> %timeit io.BytesIO(u_data) 
TypeError: 'unicode' does not have the buffer interface 
>>> %timeit io.BytesIO(b_data) 
10000 loops, best of 3: 77.5 µs per loop 
>>> %timeit cStringIO.StringIO(u_data) 
UnicodeEncodeError: 'ascii' codec cant encode character u'\u2603' in position 0: ordinal not in range(128) 
>>> %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 
+0

3.xでは' BytesIO'は 'StringIO '、2.xとは対照的に。 – Lee

+0

'io.BytesIO'と' io.StringIO'は比較できません。バイナリ入力でのみ動作し、もう一つはユニコード文字列でしか動作しません。 – Eric

+0

私は2.7テストを補完しました。たぶんあなたのポストにそれらを入れることができますか? – Lee

関連する問題