I tried to backport a Python 3 program to 2.7, and I'm stuck with a strange problem:
我试图把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'
According to the docs, io.StringIO()
returns an in-memory stream for Unicode text. It works correctly when I try and feed it a Unicode string manually. Why does it fail in conjunction with the csv
module, even if all the strings being written are Unicode strings? Where does the str
come from that causes the Exception?
根据文档,io.StringIO()返回一个用于Unicode文本的内存流。当我尝试手动输入Unicode字符串时,它可以正常工作。为什么它与csv模块一起失败,即使所写的字符串都是Unicode字符串?导致异常的str来自哪里?
(I do know that I can use StringIO.StringIO()
instead, but I'm wondering what's wrong with io.StringIO()
in this scenario)
(我知道我可以使用string . stringio(),但是我想知道在这个场景中io.StringIO()有什么问题)
4 个解决方案
#1
36
The Python 2.7 csv
module doesn't support Unicode input: see the note at the beginning of the documentation.
Python 2.7 csv模块不支持Unicode输入:请参阅文档开头的说明。
It seems that you'll have to encode the Unicode strings to byte strings, and use io.BytesIO
, instead of io.StringIO
.
似乎您必须将Unicode字符串编码为字节字符串,并使用io。BytesIO,代替io.StringIO。
The examples section of the documentation includes examples for a UnicodeReader
and UnicodeWriter
wrapper classes (thanks @AlexeyKachayev for the pointer).
该文档的示例部分包含了用于UnicodeReader和UnicodeWriter包装类的示例(感谢@AlexeyKachayev提供的指针)。
#2
22
Please use StringIO.StringIO().
请使用StringIO.StringIO()。
http://docs.python.org/library/io.html#io.StringIO
http://docs.python.org/library/io.html io.StringIO
http://docs.python.org/library/stringio.html
http://docs.python.org/library/stringio.html
io.StringIO
is a class. It handles Unicode. It reflects the preferred Python 3 library structure.
io。StringIO是一个类。它处理Unicode。它反映了首选的Python 3库结构。
StringIO.StringIO
is a class. It handles strings. It reflects the legacy Python 2 library structure.
StringIO。StringIO是一个类。它处理字符串。它反映了遗留的Python 2库结构。
#3
4
From csv
documentation:
从csv文档:
The csv module doesn’t directly support reading and writing Unicode, but it is 8-bit-clean save for some problems with ASCII NUL characters. So you can write functions or classes that handle the encoding and decoding for you as long as you avoid encodings like UTF-16 that use NULs. UTF-8 is recommended.
csv模块不直接支持读取和写入Unicode,但是它是8位清理的,保留了一些ASCII NUL字符的问题。因此,只要避免使用像UTF-16这样的编码,就可以编写处理编码和解码的函数或类。推荐utf - 8。
You can find example of UnicodeReader
, UnicodeWriter
here http://docs.python.org/2/library/csv.html
你可以在这里找到UnicodeReader的示例http://docs.python.org/2/library/csv.html
#4
4
I found this when I tried to serve a CSV file via Flask directly without creating the CSV file on the file system. This works:
当我尝试通过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()
See also
- More about CSV
- 更多关于CSV
- The Flask part
- 瓶的部分
- A few notes about Strings / Unicode
- 一些关于字符串/ Unicode的注释
#1
36
The Python 2.7 csv
module doesn't support Unicode input: see the note at the beginning of the documentation.
Python 2.7 csv模块不支持Unicode输入:请参阅文档开头的说明。
It seems that you'll have to encode the Unicode strings to byte strings, and use io.BytesIO
, instead of io.StringIO
.
似乎您必须将Unicode字符串编码为字节字符串,并使用io。BytesIO,代替io.StringIO。
The examples section of the documentation includes examples for a UnicodeReader
and UnicodeWriter
wrapper classes (thanks @AlexeyKachayev for the pointer).
该文档的示例部分包含了用于UnicodeReader和UnicodeWriter包装类的示例(感谢@AlexeyKachayev提供的指针)。
#2
22
Please use StringIO.StringIO().
请使用StringIO.StringIO()。
http://docs.python.org/library/io.html#io.StringIO
http://docs.python.org/library/io.html io.StringIO
http://docs.python.org/library/stringio.html
http://docs.python.org/library/stringio.html
io.StringIO
is a class. It handles Unicode. It reflects the preferred Python 3 library structure.
io。StringIO是一个类。它处理Unicode。它反映了首选的Python 3库结构。
StringIO.StringIO
is a class. It handles strings. It reflects the legacy Python 2 library structure.
StringIO。StringIO是一个类。它处理字符串。它反映了遗留的Python 2库结构。
#3
4
From csv
documentation:
从csv文档:
The csv module doesn’t directly support reading and writing Unicode, but it is 8-bit-clean save for some problems with ASCII NUL characters. So you can write functions or classes that handle the encoding and decoding for you as long as you avoid encodings like UTF-16 that use NULs. UTF-8 is recommended.
csv模块不直接支持读取和写入Unicode,但是它是8位清理的,保留了一些ASCII NUL字符的问题。因此,只要避免使用像UTF-16这样的编码,就可以编写处理编码和解码的函数或类。推荐utf - 8。
You can find example of UnicodeReader
, UnicodeWriter
here http://docs.python.org/2/library/csv.html
你可以在这里找到UnicodeReader的示例http://docs.python.org/2/library/csv.html
#4
4
I found this when I tried to serve a CSV file via Flask directly without creating the CSV file on the file system. This works:
当我尝试通过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()
See also
- More about CSV
- 更多关于CSV
- The Flask part
- 瓶的部分
- A few notes about Strings / Unicode
- 一些关于字符串/ Unicode的注释