Создайте файл csv utf-8 в Python
Я не могу создать файл csv utf-8 в Python.
Я пытаюсь прочитать его docs, а в разделе говорится:
Для всех остальных кодировок UnicodeReader и UnicodeWriter классы могут использоваться. Они принимают дополнительный параметр кодирования в их конструктора и убедитесь, что данные проходят реальный читатель или писатель кодируется как UTF-8:
Ok. Поэтому у меня есть этот код:
values = (unicode("Ñ", "utf-8"), unicode("é", "utf-8"))
f = codecs.open('eggs.csv', 'w', encoding="utf-8")
writer = UnicodeWriter(f)
writer.writerow(values)
И я продолжаю получать эту ошибку:
line 159, in writerow
self.stream.write(data)
File "/usr/lib/python2.6/codecs.py", line 686, in write
return self.writer.write(data)
File "/usr/lib/python2.6/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 22: ordinal not in range(128)
Может кто-нибудь, пожалуйста, дайте мне свет, чтобы я мог понять, что, черт возьми, я делаю неправильно, так как я устанавливаю всю кодировку всюду перед вызовом класса UnicodeWriter?
class UnicodeWriter:
"""
A CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
self.writer.writerow([s.encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)
Ответы
Ответ 1
Вам не нужно использовать codecs.open
; UnicodeWriter
принимает вход Unicode и заботится о кодировании всего в UTF-8. Когда UnicodeWriter
записывает в дескриптор файла, который вы ему передали, все уже находится в кодировке UTF-8 (поэтому он работает с обычным файлом, который вы открыли с помощью open
).
Используя codecs.open
, вы по существу конвертируете ваши объекты Unicode в строки UTF-8 в UnicodeWriter
, а затем попробуйте снова закодировать эти строки в UTF-8, как если бы эти строки содержали строки Unicode, которые, очевидно, не выполняются.
Ответ 2
Как вы поняли, это работает, если вы используете простой открытый файл.
Причиной этого является то, что вы пытались дважды кодировать UTF-8. Однажды в
f = codecs.open('eggs.csv', 'w', encoding="utf-8")
а затем в UnicodeWriter.writeRow
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
Чтобы проверить, что это работает, используйте исходный код и прервите эту строку.
Greetz
Ответ 3
Я столкнулся с вызовом csv/unicode некоторое время назад и бросил это на битбакет: http://bitbucket.org/famousactress/dude_csv.. может работать для вас, если ваши потребности просты:)
Ответ 4
Вам не нужно "дважды кодировать" все.
Ваше приложение должно работать полностью в Юникоде.
Сделайте свою кодировку только в codecs.open
для записи байтов UTF-8 во внешний файл. Никакой другой кодировки в вашем приложении.