用于读取 ZIP 存档中的 CSV 文件的简单程序:
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
适用于 Python 2.7:
$ python2.7 test_zip_file_py3k.py ~/data.zip
$
但不是在 Python 3.2 中:
$ 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 "/somedir/python3.2/csv.py", line 109, in __next__
self.fieldnames
File "/somedir/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?)
Python 3 中的 csv
模块想要查看文本文件,但是 zipfile.ZipFile.open
返回一个 zipfile.ZipExtFile
始终被视为二进制数据。
如何在 Python 3 中实现这一点?
原文由 Marc Abramowitz 发布,翻译遵循 CC BY-SA 4.0 许可协议
我只是注意到 Lennart 的回答 不适用于 Python 3.1 ,但它 确实 适用于 Python 3.2 。他们在 Python 3.2 中增强了
zipfile.ZipExtFile
(参见 发行说明)。这些更改似乎使zipfile.ZipExtFile
与io.TextWrapper
--- 配合得很好。顺便说一下,它在 Python 3.1 中工作,如果你取消注释下面的 hacky 行到 monkey-patch
zipfile.ZipExtFile
,并不是说我会推荐这种 hackery。我包含它只是为了说明在 Python 3.2 中所做的工作的本质,以使事情很好地工作。如果我必须支持 py3k < 3.2,那么我会使用 其他答案 中的解决方案。
更新 3.6+
从 w/3.6 开始,删除了对
mode='U'
的支持 ^1 :从 w/3.8 开始,添加了一个 Path 对象,它为我们提供了一个
open()
我们可以调用的方法,就像内置的open()
函数(传递newline=''
-ee-7286我们的 CSV 的例子),我们得到一个 io.TextIOWrapper 对象,csv 读者接受。 在此处 查看 Yuri 的回答。