Python 如何将io.StringIO()与csv模块一起使用?

Python 如何将io.StringIO()与csv模块一起使用?,python,csv,unicode,python-2.7,Python,Csv,Unicode,Python 2.7,我试图将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 "<s

我试图将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 >>>导入csv >>>输出=io.StringIO() >>>output.write(“Hello!”)#失败:io.StringIO需要Unicode 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:应为unicode参数,得到'str' >>>output.write(u“Hello!”)#这一切正常。 6L >>>writer=csv.writer(output)#现在让我们用csv模块试试这个: >>>csvdata=[u“你好”,u“再见”]#瞧,妈,全是Unicode!(?) >>>writer.writerow(csvdata)#遗憾的是,没有。 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:应为unicode参数,得到'str' 根据文档,返回Unicode文本的内存流。当我尝试手动输入Unicode字符串时,它工作正常。为什么它与
csv
模块一起失败,即使写入的所有字符串都是Unicode字符串?导致异常的
str
来自哪里


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

Python2.7
csv
模块不支持Unicode输入:请参阅

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


文档部分包括
UnicodeReader
UnicodeWriter
包装类的示例(感谢@AlexeyKachayev的指针)。来自
csv
文档:

csv模块不直接支持读取和写入Unicode, 但它是8位干净的,除了ASCII NUL的一些问题 人物。因此,您可以编写函数或类来处理 只要您避免像这样的编码,就可以为您进行编码和解码 使用NUL的UTF-16。建议使用UTF-8


您可以在这里找到
UnicodeReader
UnicodeWriter
的示例

请使用StringIO.StringIO()

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


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

当我试图通过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()
另见

要在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)

我的问题与OP完全相同(尽管只是在我的单元测试中,而不是在提示时)。无论如何,在Python3中使用
io.StringIO
,在Python2中使用
io.BytesIO
,正如这个答案中所建议的,解决了我的问题。我怀疑当从使用“bytestring literals”AttributeError:type对象“\u io.StringIO”的stdlib模块中进行子类化时,python2中导入unicode文字的
可能会导致此问题