【问题标题】:How to read a csv django http response如何读取 csv django http 响应
【发布时间】:2016-10-26 11:20:30
【问题描述】:

在一个视图中,我使用简单的 csv 编写器创建了一个完全由 csv 组成的 Django HttpResponse 对象:

response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="foobar.csv"'

writer = csv.writer(response)

    table_headers = ['Foo', 'Bar']
    writer.writerow(table_headers)

    bunch_of_rows = [['foo', 'bar'], ['foo2', 'bar2']]
    for row in bunch_of_rows:
        writer.writerow(row)

return response

在单元测试中,我想测试这个 csv 的某些方面,所以我需要阅读它。我正在尝试这样做:

response = views.myview(args)

reader = csv.reader(response.content)

headers = next(reader)
row_count = 1 + sum(1 for row in reader)

self.assertEqual(row_count, 3) # header + 1 row for each attempt
self.assertIn('Foo', headers)

但测试失败,headers = next(reader) 行显示以下内容:

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

我在 HttpResponse 源中看到 response.content 将字符串作为字节字符串吐出,但我不确定正确的处理方法是让 csv.reader 正确读取文件。我以为我可以将response.content 替换为response(因为您写入对象本身,而不是其内容),但这只会导致错误略有变化:

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

这似乎更接近,但显然仍然是错误的。阅读csv 文档,我认为我无法正确打开文件。如何“打开”这个类文件对象以便csv.reader 可以解析它?

【问题讨论】:

    标签: python django csv


    【解决方案1】:

    response.content 提供字节。您需要将其解码为字符串:

    foo = response.content.decode('utf-8')
    

    然后使用 io.StringIO 将此字符串传递给 csv 阅读器:

    import io
    reader = csv.reader(io.StringIO(foo))
    

    【讨论】:

    • 虽然两个答案都是有效的,但在我的特殊情况下,内容是如此之小,以至于 knbk 的答案所提供的微小性能改进被这个答案的可读性所抵消。两个都赞成,这个接受了。我最终使用的最终形式是:reader = csv.reader(StringIO(response.content.decode('utf-8')))。我选择只导入 StringIO,因此省略了io.
    【解决方案2】:

    您可以使用io.TextIOWrapper 将提供的字节串转换为文本流:

    import io
    reader = csv.reader(io.TextIOWrapper(io.BytesIO(response.content), encoding='utf-8'))
    

    这将在阅读器读取字节时将其转换为字符串。

    【讨论】:

    • 将我的 reader = 行替换为您的行,我收到错误:AttributeError: 'bytes' object has no attribute 'readable'。正在调查...
    • 经过进一步调查,我最初的评论是错误的。要使用它,您首先需要先将 response.content 传递给 BytesIO。
    • 你说得对。它确实具有解码块的优点,而不是一次解码所有内容,但通常不会有任何区别。在大多数情况下,您的答案更易于使用,但为了完整起见,我将把它留在这里。
    猜你喜欢
    • 2014-01-16
    • 1970-01-01
    • 2016-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    • 2019-03-14
    • 1970-01-01
    相关资源
    最近更新 更多