【发布时间】:2016-01-16 03:08:22
【问题描述】:
我正在尝试编写一个与 Python 2/3 兼容的例程来获取 CSV 文件,将其从 latin_1 解码为 Unicode,并以稳健、可扩展的方式将其提供给 csv.DictReader。
- 为了支持 Python 2/3,我使用
python-future,包括从builtins导入open,并导入unicode_literals以实现一致的行为 - 我希望通过使用
tempfile.SpooledTemporaryFile溢出到磁盘来处理异常大的文件 - 我使用
io.TextIOWrapper处理从latin_1编码解码,然后再输入DictReader
这在 Python 3 下一切正常。
问题是TextIOWrapper 期望包装一个符合BufferedIOBase 的流。不幸的是,在 Python 2 下,虽然我已经导入了 Python 3 风格的 open,但原版 Python 2 tempfile.SpooledTemporaryFile 当然仍然返回 Python 2 cStringIO.StringO,而不是 TextIOWrapper 要求的 Python 3 io.BytesIO .
我能想到这些可能的方法:
- 将 Python 2
cStringIO.StringO包装为 Python 3 样式的io.BytesIO。我不确定如何解决这个问题 - 我需要编写这样的包装器还是已经存在? - 找到一个 Python 2 替代方案来包装
cStringIO.StringO流进行解码。我还没有找到。 - 取消
SpooledTemporaryFile,完全在内存中解码。 CSV 文件需要多大才能完全在内存中运行才能成为一个问题? - 取消
SpooledTemporaryFile,并实现我自己的溢出到磁盘。这将允许我从 python-future 调用open,但我宁愿不这样做,因为它会非常乏味并且可能不太安全。
最好的前进方式是什么?我错过了什么吗?
进口:
from __future__ import (absolute_import, division,
print_function, unicode_literals)
from builtins import (ascii, bytes, chr, dict, filter, hex, input, # noqa
int, map, next, oct, open, pow, range, round, # noqa
str, super, zip) # noqa
import csv
import tempfile
from io import TextIOWrapper
import requests
初始化:
...
self._session = requests.Session()
...
例行公事:
def _fetch_csv(self, path):
raw_file = tempfile.SpooledTemporaryFile(
max_size=self._config.get('spool_size')
)
csv_r = self._session.get(self.url + path)
for chunk in csv_r.iter_content():
raw_file.write(chunk)
raw_file.seek(0)
text_file = TextIOWrapper(raw_file._file, encoding='latin_1')
return csv.DictReader(text_file)
错误:
...in _fetch_csv
text_file = TextIOWrapper(raw_file._file, encoding='utf-8')
AttributeError: 'cStringIO.StringO' object has no attribute 'readable'
【问题讨论】:
-
我遇到了类似的问题,没有找到比为 Python 2 和 3 编写单独的代码然后检测您正在运行的版本更好的解决方案。
-
@cbare 是的,我怀疑它可能归结为这一点。您有机会发布您的解决方案吗?
标签: python python-2.7 python-3.x character-encoding temporary-files