Python 如何将io.StringIO()与csv模块一起使用?
我试图将Python 3程序向后移植到2.7,但遇到了一个奇怪的问题: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
>>> 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.7csv
模块不支持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()
另见
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文字的可能会导致此问题