【问题标题】:How can I use io.StringIO() with the csv module?如何将 io.StringIO() 与 csv 模块一起使用?
【发布时间】:2012-10-18 16:17:36
【问题描述】:

我尝试将 Python 3 程序反向移植到 2.7,但遇到了一个奇怪的问题:

>>> import io
>>> import csv
>>> output = io.StringIO()
>>> output.write("Hello!")            # Fail: io.StringIO expects Unicode
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'
>>> output.write(u"Hello!")           # This works as expected.
6L
>>> writer = csv.writer(output)       # Now let's try this with the csv module:
>>> csvdata = [u"Hello", u"Goodbye"]  # Look ma, all Unicode! (?)
>>> writer.writerow(csvdata)          # Sadly, no.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'

根据文档,io.StringIO() 返回 Unicode 文本的内存流。当我尝试手动为其提供 Unicode 字符串时,它可以正常工作。为什么它与csv 模块一起失败,即使正在写入的所有字符串都是Unicode 字符串?导致异常的str 来自哪里?

(我知道我可以改用StringIO.StringIO(),但我想知道在这种情况下io.StringIO() 有什么问题)

【问题讨论】:

  • 我怀疑 from __future__ import unicode_literals 在从使用“字节串文字”的 stdlib 模块子类化时可能会在 python2 中导致此问题

标签: python csv unicode python-2.7


【解决方案1】:

Python 2.7 csv 模块不支持 Unicode 输入:请参阅 note at the beginning of the documentation

看来您必须将 Unicode 字符串编码为字节字符串,并使用io.BytesIO,而不是io.StringIO

文档的examples 部分包含UnicodeReaderUnicodeWriter 包装类的示例(感谢@AlexeyKachayev 提供的指针)。

【讨论】:

  • 我遇到了与 OP 完全相同的问题(尽管只是在我的单元测试中,而不是在提示中,奇怪的是)。无论如何,按照这个答案的建议,在 Python 3 中使用 io.StringIO 和在 Python 2 中使用 io.BytesIO 解决了我的问题。
【解决方案2】:

请使用 StringIO.StringIO()。

http://docs.python.org/library/io.html#io.StringIO

http://docs.python.org/library/stringio.html

io.StringIO 是一个类。它处理 Unicode。它反映了首选的 Python 3 库结构。

StringIO.StringIO 是一个类。它处理字符串。它反映了传统的 Python 2 库结构。

【讨论】:

  • AttributeError: type object '_io.StringIO' has no attribute 'StringIO'
【解决方案3】:

当我尝试通过 Flask 直接提供 CSV 文件而不在文件系统上创建 CSV 文件时,我发现了这一点。这有效:

import io
import csv

data = [[u'cell one', u'cell two'], [u'cell three', u'cell four']]

output = io.BytesIO()
writer = csv.writer(output, delimiter=',')
writer.writerows(data)
your_csv_string = output.getvalue()

另见

【讨论】:

    【解决方案4】:

    来自csv 文档:

    csv 模块不直接支持读写 Unicode, 但对于 ASCII NUL 的一些问题,它是 8 位干净的 人物。所以你可以编写函数或类来处理 只要您避免像这样的编码,就可以为您编码和解码 使用 NUL 的 UTF-16。推荐使用 UTF-8。

    您可以在此处找到UnicodeReaderUnicodeWriter 的示例http://docs.python.org/2/library/csv.html

    【讨论】:

      【解决方案5】:

      在 python 2.7 中将 CSV 读取器/写入器与“内存文件”一起使用:

      from io import BytesIO
      import csv
      
      csv_data = """a,b,c
      foo,bar,foo"""
      
      # creates and stores your csv data into a file the csv reader can read (bytes)
      memory_file_in = BytesIO(csv_data.encode(encoding='utf-8'))
      
      # classic reader
      reader = csv.DictReader(memory_file_in)
      
      # writes a csv file
      fieldnames = reader.fieldnames  # here we use the data from the above csv file
      memory_file_out = BytesIO()     # create a memory file (bytes)
      
      # classic writer (here we copy the first file in the second file)
      writer = csv.DictWriter(memory_file_out, fieldnames)
      for row in reader:
          print(row)
          writer.writerow(row)
      

      【讨论】:

        猜你喜欢
        • 2018-11-13
        • 2014-05-21
        • 2021-12-26
        • 2018-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        相关资源
        最近更新 更多