Юникод (UTF-8) чтение и запись в файлы на Python - PullRequest
289 голосов
/ 29 января 2009

У меня какая-то мозговая ошибка в понимании чтения и записи текста в файл (Python 2.4).

# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)

(«u'Capit \ xe1n», «Capit \ xc3 \ xa1n»)

print ss, ss8
print >> open('f1','w'), ss8

>>> file('f1').read()
'Capit\xc3\xa1n\n'

Поэтому я набираю Capit\xc3\xa1n в моем любимом редакторе, в файле f2.

Тогда:

>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'

Что я не понимаю здесь? Ясно, что я пропускаю какое-то жизненно важное волшебство (или здравый смысл). Что вводить в текстовые файлы, чтобы получить правильные преобразования?

Что я действительно не могу понять, так это смысл представления UTF-8, если вы не можете заставить Python распознавать его, когда оно приходит извне. Может быть, я должен просто JSON вывести строку и использовать ее вместо этого, так как это имеет превосходное представление! Более того, существует ли ASCII-представление этого объекта Unicode, которое Python будет распознавать и декодировать при входе из файла? Если так, как я могу получить это?

>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'

Ответы [ 13 ]

4 голосов
/ 29 января 2009

Последовательность \ x .. специфична для Python. Это не универсальная escape-последовательность байтов.

То, как вы на самом деле вводите кодировку в кодировке UTF-8, не являющуюся ASCII, зависит от вашей ОС и / или вашего редактора. Вот как вы это делаете в Windows . Чтобы OS X ввела a с острым акцентом, вы можете просто нажать option + E , затем A и почти все текстовые редакторы. в OS X поддерживается UTF-8.

3 голосов
/ 08 декабря 2016

Вы также можете улучшить исходную функцию open() для работы с файлами Unicode, заменив ее на месте, используя функцию partial. Прелесть этого решения в том, что вам не нужно менять старый код. Это прозрачно.

import codecs
import functools
open = functools.partial(codecs.open, encoding='utf-8')
1 голос
/ 10 мая 2016

Я пытался разобрать iCal , используя Python 2.7.9:

из календаря импорта icalendar

Но я получал:

 Traceback (most recent call last):
 File "ical.py", line 92, in parse
    print "{}".format(e[attr])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe1' in position 7: ordinal not in range(128)

и это было исправлено просто:

print "{}".format(e[attr].encode("utf-8"))

(Теперь он может печатать как у меня).

...