Создайте CSV-файл utf-8 в Python - PullRequest
17 голосов
/ 21 июня 2010

Я не могу создать CSV-файл utf-8 в Python.

Я пытаюсь прочитать его документы, а в разделе примеры написано:

Для всех других кодировок могут использоваться следующие классы 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)

Ответы [ 4 ]

14 голосов
/ 21 июня 2010

Вам не нужно использовать codecs.open;UnicodeWriter принимает ввод Unicode и заботится о кодировании всего в UTF-8.Когда UnicodeWriter записывает в дескриптор файла, который вы ему передали, все уже находится в кодировке UTF-8 (поэтому он работает с обычным файлом, который вы открыли с помощью open).

Используя codecs.open,вы по существу конвертируете свои объекты Unicode в строки UTF-8 в UnicodeWriter, а затем снова пытаетесь перекодировать эти строки в UTF-8, как если бы эти строки содержали строки Unicode, что явно не сработало.

1 голос
/ 22 июня 2010

Я столкнулся с проблемой csv / unicode некоторое время назад и бросил это в bitbucket: http://bitbucket.org/famousactress/dude_csv .. может работать для вас, если ваши потребности просты:)

1 голос
/ 21 июня 2010

Как вы уже поняли, это работает, если вы используете открытое открытие.

Причина этого в том, что вы пытались кодировать 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

0 голосов
/ 21 июня 2010

Вам не нужно все дважды кодировать.

Ваше приложение должно работать полностью в Unicode.

Используйте кодирование только в codecs.open для записи байтов UTF-8 во внешний файл. Не используйте другую кодировку в вашем приложении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...