【问题标题】:csv.reader read from Requests stream: iterator should return strings, not bytescsv.reader 从请求流中读取:迭代器应该返回字符串,而不是字节
【发布时间】:2017-01-29 21:19:15
【问题描述】:

我正在尝试使用requests.get(url, stream=True)csv.reader 进行流式响应,以处理相当大的数据馈送。我的代码在python2.7 上运行良好。代码如下:

response = requests.get(url, stream=True)
ret = csv.reader(response.iter_lines(decode_unicode=True), delimiter=delimiter, quotechar=quotechar,
    dialect=csv.excel_tab)
for line in ret:
    line.get('name')

不幸的是,迁移到python3.6后出现以下错误:

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

我试图找到一些包装器/装饰器,它将response.iter_lines() 迭代器的结果从字节转换为字符串,但没有运气。 我已经尝试使用io 包和codecs。使用codecs.iterdecode 不会按行拆分数据,它可能只是被chunk_size 拆分, 在这种情况下,csv.reader 以下列方式抱怨:

_csv.Error: new-line character seen in unquoted field - do you need to open the file in universal-newline mode?

【问题讨论】:

  • iter_lines() 是一个生成器,所以我不能在那个(?)上解码()。另一方面,生成器上使用的 lambda 表达式不会用所有数据填充我的内存吗?我想省略它,这就是为什么我首先要流式传输它。
  • 你说得对,那是行不通的。您必须创建一个生成器,它调用原始生成器并即时解码字节。不知道该怎么做。
  • @Jean-FrançoisFabre 对,我想...我可能会为此编写一些包装生成器,但也许有人会想出一个更漂亮的解决方案。

标签: python django python-3.x csv python-requests


【解决方案1】:

我猜你可以将它包装在 genexp 中并将解码后的行提供给它:

from contextlib import closing

with closing(requests.get(url, stream=True)) as r:
    f = (line.decode('utf-8') for line in r.iter_lines())
    reader = csv.reader(f, delimiter=',', quotechar='"')
    for row in reader:
        print(row)

使用3.5 中的一些样本数据会关闭csv.reader,输入给它的每一行都是第一个decoded 在genexp 中。另外,我正在使用contextlib 中的closinggenerally suggested 一样自动响应close

【讨论】:

  • 对,genexp 已经足够好了。感谢closing 部分,我不知道这一点。
猜你喜欢
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 2023-01-22
  • 2020-01-10
  • 1970-01-01
  • 2020-12-17
  • 2018-02-15
相关资源
最近更新 更多