38

zip ファイル内の CSV ファイルを読み取る単純なプログラムは、Python 2.7 では機能しますが、Python 3.2 では機能しません。

$ cat test_zip_file_py3k.py 
import csv, sys, zipfile

zip_file    = zipfile.ZipFile(sys.argv[1])
items_file  = zip_file.open('items.csv', 'rU')

for row in csv.DictReader(items_file):
    pass

$ python2.7 test_zip_file_py3k.py ~/data.zip

$ python3.2 test_zip_file_py3k.py ~/data.zip
Traceback (most recent call last):
  File "test_zip_file_py3k.py", line 8, in <module>
    for row in csv.DictReader(items_file):
  File "/home/msabramo/run/lib/python3.2/csv.py", line 109, in __next__
    self.fieldnames
  File "/home/msabramo/run/lib/python3.2/csv.py", line 96, in fieldnames
    self._fieldnames = next(self.reader)
_csv.Error: iterator should return strings, not bytes (did you open the file 
in text mode?)

したがって、csvPython 3 のモジュールはテキスト ファイルを見たいと思っていますが、常にバイナリ データとして扱われる をzipfile.ZipFile.open返します。zipfile.ZipExtFile

Python 3でこれをどのように機能させるのですか?

4

5 に答える 5

33

Lennart の回答が Python 3.1では機能しないことに気付きましたが、 Python 3.2では機能します。それらはzipfile.ZipExtFilePython 3.2 で拡張されました (リリース ノートを参照)。これらの変更は とzipfile.ZipExtFileうまく機能するようio.TextWrapperです。

ちなみに、Python 3.1 では動作しますが、以下のハッキーな行のコメントを解除して monkey-patchzipfile.ZipExtFileにすると、私はこの種のハッカーをお勧めしません。Python 3.2 でうまく機能させるために行われたことの本質を説明するためだけにこれを含めます。

$ cat test_zip_file_py3k.py 
import csv, io, sys, zipfile

zip_file    = zipfile.ZipFile(sys.argv[1])
items_file  = zip_file.open('items.csv', 'rU')
# items_file.readable = lambda: True
# items_file.writable = lambda: False
# items_file.seekable = lambda: False
# items_file.read1 = items_file.read
items_file  = io.TextIOWrapper(items_file)

for idx, row in enumerate(csv.DictReader(items_file)):
    print('Processing row {0} -- row = {1}'.format(idx, row))

py3k < 3.2 をサポートする必要がある場合は、他の回答のソリューションを使用します。

于 2011-04-12T18:34:35.250 に答える
14

io.TextIOWrapperでラップできます。

items_file  = io.TextIOWrapper(items_file, encoding='your-encoding', newline='')

動作するはずです。

于 2011-04-12T07:25:51.957 に答える
3

レナートの答えは正しい方向に進んでおり(ありがとう、レナート、私はあなたの答えに投票しました)、ほとんどうまくいきます:

$ cat test_zip_file_py3k.py 
import csv, io, sys, zipfile

zip_file    = zipfile.ZipFile(sys.argv[1])
items_file  = zip_file.open('items.csv', 'rU')
items_file  = io.TextIOWrapper(items_file, encoding='iso-8859-1', newline='')

for idx, row in enumerate(csv.DictReader(items_file)):
    print('Processing row {0}'.format(idx))

$ python3.1 test_zip_file_py3k.py ~/data.zip
Traceback (most recent call last):
  File "test_zip_file_py3k.py", line 7, in <module>
    items_file  = io.TextIOWrapper(items_file, 
                                   encoding='iso-8859-1', 
                                   newline='')
AttributeError: readable

問題は、io.TextWrapperの最初の必須パラメータがバッファであることです。ファイルオブジェクトではありません。

これはうまくいくようです:

items_file  = io.TextIOWrapper(io.BytesIO(items_file.read()))

これは少し複雑に思えますし、(おそらく巨大な) zip ファイル全体をメモリに読み込まなければならないのも煩わしいようです。もっと良い方法はありますか?

これが実際の動作です:

$ cat test_zip_file_py3k.py 
import csv, io, sys, zipfile

zip_file    = zipfile.ZipFile(sys.argv[1])
items_file  = zip_file.open('items.csv', 'rU')
items_file  = io.TextIOWrapper(io.BytesIO(items_file.read()))

for idx, row in enumerate(csv.DictReader(items_file)):
    print('Processing row {0}'.format(idx))

$ python3.1 test_zip_file_py3k.py ~/data.zip
Processing row 0
Processing row 1
Processing row 2
...
Processing row 250
于 2011-04-12T17:59:08.980 に答える