Как я могу использовать io.StringIO() с модулем csv?
Я попытался перенести программу 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()
по этому сценарию)
4 ответа
Питон 2.7 csv
Модуль не поддерживает ввод Unicode: см. примечание в начале документации.
Кажется, что вам придется кодировать строки Unicode в байтовые строки, и использовать io.BytesIO
, вместо io.StringIO
,
Раздел примеров документации содержит примеры для UnicodeReader
а также UnicodeWriter
классы-обертки (спасибо @AlexeyKachayev за указатель).
Пожалуйста, используйте StringIO.StringIO ().
http://docs.python.org/library/io.html
http://docs.python.org/library/stringio.html
io.StringIO
это класс. Он обрабатывает Unicode. Он отражает предпочтительную структуру библиотеки Python 3.
StringIO.StringIO
это класс. Он обрабатывает строки. Он отражает устаревшую структуру библиотеки Python 2.
Я обнаружил это, когда попытался подать файл CSV напрямую через Flask, не создавая файл 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()
Смотрите также
От csv
документация:
Модуль csv напрямую не поддерживает чтение и запись Unicode, но он 8-разрядный, за исключением некоторых проблем с символами ASCII NUL. Таким образом, вы можете написать функции или классы, которые обрабатывают кодирование и декодирование для вас, если вы избегаете кодировок, таких как UTF-16, которые используют NUL. UTF-8 рекомендуется.
Вы можете найти пример UnicodeReader
, UnicodeWriter
здесь http://docs.python.org/2/library/csv.html
Чтобы использовать программу чтения / записи CSV с файлами памяти в python 2.7:
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)