Экспорт Python Unicode CSV (с использованием Django) - PullRequest
5 голосов
/ 14 октября 2010

Я использую приложение Django для экспорта строки в файл CSV.Строка - это сообщение, которое было отправлено через форму интерфейса пользователя.Тем не менее, я получаю эту ошибку, когда во входных данных предоставляется одинарная кавычка Unicode.

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2019' 
  in position 200: ordinal not in range(128)

Я пытался преобразовать юникод в ascii, используя приведенный ниже код, но все равно получаю похожую ошибку.

UnicodeEncodeError: 'ascii' codec can't encode characters in 
position 0-9: ordinal not in range(128)

Я просмотрел десятки веб-сайтов и многое узнал о юникоде, однако до сих пор не могу конвертировать этот юникод в ascii.Мне все равно, если алгоритм удаляет символы Unicode.Закомментированные строки указывают на некоторые различные варианты, которые я пробовал, но ошибка сохраняется.

import csv
import unicodedata

...

#message = unicode( unicodedata.normalize(
#                            'NFKD',contact.message).encode('ascii','ignore'))
#dmessage = (contact.message).encode('utf-8','ignore')
#dmessage = contact.message.decode("utf-8")
#dmessage = "%s" % dmessage
dmessage = contact.message

csv_writer.writerow([
        dmessage,
])

У кого-нибудь есть советы по удалению символов Юникода, чтобы я мог экспортировать их в CSV?Эта, казалось бы, легкая проблема заставляла мою голову кружиться.Буду признателен за любую оказанную помощь.Спасибо, Джо

Ответы [ 3 ]

7 голосов
/ 14 октября 2010

Нельзя кодировать символ Unicode u'\u2019' (правая одинарная кавычка U + 2019) в ASCII, поскольку в ASCII этот символ отсутствует. ASCII - это только основной латинский алфавит, цифры и знаки препинания; у вас нет акцентированных букв или «умных цитат», подобных этому персонажу.

Так что вам придется выбрать другую кодировку. Теперь обычно разумно было бы экспортировать в UTF-8, который может содержать любой символ Unicode. К сожалению для вас, если ваши целевые пользователи используют Office (и они, вероятно, используют), они не смогут читать символы в кодировке UTF-8 в CSV. Вместо этого Excel будет читать файлы, используя системную кодовую страницу по умолчанию для этого компьютера (также вводящую в заблуждение как кодовую страницу «ANSI»), и в итоге получит моджибаке, например ’ вместо .

Это означает, что вам нужно угадать системную кодовую страницу по умолчанию, если вы хотите, чтобы символы правильно отображались. Для западных пользователей это будет кодовая страница 1252. Пользователи с незападными установками Windows увидят неправильные символы, но с этим ничего не поделаешь (кроме как организовать кампанию по написанию писем в Microsoft, чтобы просто отбросить глупую чепуху с ANSI уже и использовать UTF-8, как и все).

Кодовая страница 1252 может содержать U + 2019 (), но, очевидно, есть еще много символов, которые она не может представлять. Чтобы избежать получения UnicodeEncodeError для этих символов, вы можете использовать аргумент ignore (или replace, чтобы заменить их знаками вопроса).

dmessage= contact.message.encode('cp1252', 'ignore')

в качестве альтернативы, чтобы отказаться от всех не-ASCII символов, чтобы каждый получил одинаково плохой опыт независимо от локали:

dmessage= contact.message.encode('ascii', 'ignore')
2 голосов
/ 14 октября 2010

Кодирование - это боль, но если вы работаете в django, вы пробовали smart_unicode(str) из django.utils.encoding? Я считаю, что это обычно помогает.

Единственный другой вариант, который я нашел, это использовать встроенные python encode() и decode() для строк, но вы должны указать кодировку для них и, честно говоря, это боль.

1 голос
/ 14 октября 2010

[предостережение: я не джангуист; Джанго может иметь лучшее решение].

Общий, не относящийся к джанго, ответ:

Если у вас есть небольшое количество известных не ASCII-символов и для них есть приемлемые для пользователя эквиваленты ASCII, вы можете настроить таблицу перевода и использовать метод unicode.translate:

smashcii = {
    0x2019 : u"'",
    # etc
    #

smashed = input_string.translate(smashcii)
...