Проблема с юникодом Python - PullRequest
2 голосов

Я получаю некоторые данные из ZODB (База данных объектов Zope). Я получаю mybrains объект. Тогда я делаю:

o = mybrains.getObject()

и я получаю объект "Персона" в моем проекте. Тогда я могу сделать

b = o.name

и делая print b в моем классе, я получаю:

José Carlos

и print b.name.__class__

<type 'unicode'>

У меня много объектов "Персона". Они добавляются в список.

names = [o.nome, o1.nome, o2.nome]

Затем я пытаюсь создать текстовый файл с этими данными.

delimiter = ';'
all = delimiter.join(names) + '\n'

Нет проблем. Теперь, когда я делаю print all, у меня есть:

José Carlos;Jonas;Natália
Juan;John

Но когда я пытаюсь создать файл из него:

f = open("/tmp/test.txt", "w")
f.write(all)

Я получаю такую ​​ошибку (позиции не совпадают, так как я меняю имена)

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

Если я могу печатать уже с «правильной» формой для отображения, почему я не могу написать файл с ней? Какой метод кодирования / декодирования я должен использовать для записи файла с этими данными?

Я использую Python 2.4.5 (не могу его обновить)

Ответы [ 2 ]

3 голосов
/ 28 мая 2010

UnicodeEncodeError: 'ascii' кодек

write пытается кодировать строку, используя кодек ascii (у которого нет способа кодирования символов с ударением, таких как é или à.

Вместо этого используйте

import codecs
with codecs.open("/tmp/test.txt",'w',encoding='utf-8') as f:   
    f.write(all.decode('utf-8'))

или выберите другой кодек (например, cp1252), который может кодировать символы в вашей строке.

PS. all.decode('utf-8') был использован выше, потому что f.write ожидает Unicode-строку. Лучше, чем использовать all.decode('utf-8'), будет конвертировать все ваши строки в ранний Unicode, работать в юникоде и кодировать в определенную кодировку, например, 'utf-8' позднее, - только тогда, когда это необходимо. *

ПФС. Похоже, что names может быть уже списком строк Unicode. В этом случае определите delimiter как строку в юникоде: delimiter = u';', так что all будет строкой в ​​юникоде. Тогда

with codecs.open("/tmp/test.txt",'w',encoding='utf-8') as f:   
    f.write(all)

должно работать (если нет каких-либо проблем с Python 2.4, о которых я не знаю.)

Если 'utf-8' не работает, не забудьте попробовать другие кодировки, которые содержат символы, которые вам нужны, и о которых ваш компьютер знает. В Windows это может означать «cp1252».

0 голосов
/ 28 мая 2010

Вы сказали Python печатать all, но поскольку all не имеет фиксированного представления компьютера, Python сначала должен был преобразовать all в какую-либо печатную форму. Поскольку вы не указали Python, как выполнять преобразование, он предполагал, что вам нужен ASCII. К сожалению, ASCII может обрабатывать только значения от 0 до 127, а all содержит значения вне этого диапазона, поэтому вы видите ошибку.

Чтобы исправить это, используйте:

all = "José Carlos;Jonas;Natália Juan;John"
import codecs
f = codecs.open("/tmp/test.txt", "w", "utf-8")
f.write(all.decode("utf-8"))
f.close()
...