Почему происходит сбой печати в файл utf-8? - PullRequest
2 голосов
/ 30 июня 2011

Итак, я столкнулся с проблемой сегодня днем, я смог ее решить, но я не совсем понимаю, почему это сработало.

это связано с проблемой, с которой я столкнулся на прошлой неделе: проверка python, если строка utf-8 прописна

в основном, следующее не будет работать:

#!/usr/bin/python

import codecs
from lxml import etree

outFile = codecs.open('test.xml', 'w', 'utf-8') #cannot use codecs.open()

root = etree.Element('root')
sect = etree.SubElement(root,'sect')


words = (   u'\u041c\u041e\u0421\u041a\u0412\u0410', # capital of Russia, all uppercase
            u'R\xc9SUM\xc9',    # RESUME with accents
            u'R\xe9sum\xe9',    # Resume with accents
            u'R\xe9SUM\xe9', )  # ReSUMe with accents

for word in words:
    print word
    if word.encode('utf8').decode('utf8').isupper(): #.isupper won't function on utf8 
        title = etree.SubElement(sect,'title')
        title.text = word
    else:
       item = etree.SubElement(sect,'item')
       item.text = word 

print>>outFile,etree.tostring(root,pretty_print=True,xml_declaration=True,encoding='utf-8')

происходит сбой со следующим:

Трассировка (последний последний вызов):
Файл "./temp.py", строка 25, в
печать>> outFile, etree.tostring (root, pretty_print = True, xml_declaration = True, encoding = 'utf-8')
Файл "/usr/lib/python2.7/codecs.py",
строка 691,при записи
возвращает файл self.writer.write (data) "/usr/lib/python2.7/codecs.py",
строка 351, при записи
данные, потребляется = self.encode (объект, self.errors)
UnicodeDecodeError: кодек 'ascii'
не может декодировать байт 0xd0 в позиции 66:
порядковый номер не в диапазоне (128)

, но если я откроюновый файл без codecs.open('test.xml', 'w', 'utf-8') и вместо него outFile = open('test.xml', 'w') работает отлично.

Так что же происходит ??

  • , поскольку encoding='utf-8' указано в etree.tostring() это кодировка файла снова?

  • если я оставлю codecs.open() и удалю encoding='utf-8', то файл станет файлом ascii.Зачем?потому что etree.tostring() имеет кодировку по умолчанию ascii, я полагаю?

  • но etree.tostring() просто записывается в стандартный вывод, а затем перенаправляется в файл, который был создан как файл utf-8 ??

    • разве print>> не работает, как я ожидаю?outFile.write(etree.tostring()) ведет себя так же.

В принципе, почему бы это не сработало?что происходит здесь.Это может быть тривиально, но я, очевидно, немного смущен и хочу выяснить, почему мое решение работает,

Ответы [ 3 ]

3 голосов
/ 30 июня 2011

Вы открыли файл с кодировкой UTF-8, что означает, что он ожидает строки Unicode.

tostring - это кодировка UTF-8 (в виде строк байтов, str), которую вы записываете в файл.

Поскольку файл ожидает Unicode, он декодирует строки байтов в Unicode, используя кодировку ASCII по умолчанию, чтобы затем можно было кодировать Unicode в UTF-8.

К сожалению, байтовые строки не являются ASCII.

РЕДАКТИРОВАТЬ: лучший совет, чтобы избежать такого рода проблем, это использовать внутреннее Unicode, декодирование на входе и кодирование на выходе.

1 голос
/ 30 июня 2011

Использование print>>outFile немного странно.У меня не установлена ​​lxml, но встроенная библиотека xml.etree похожа (но не поддерживает pretty_print).Оберните элемент root в ElementTree и используйте метод записи.

Также, если вы используете строку # coding для объявления кодировки исходного файла, вы можете использовать читаемые строки Юникода вместо escape-кодов:

#!/usr/bin/python
# coding: utf8

import codecs
from xml.etree import ElementTree as etree

root = etree.Element(u'root')
sect = etree.SubElement(root,u'sect')


words = [u'МОСКВА',u'RÉSUMÉ',u'Résumé',u'RéSUMé']

for word in words:
    print word
    if word.isupper():
        title = etree.SubElement(sect,u'title')
        title.text = word
    else:
       item = etree.SubElement(sect,u'item')
       item.text = word 

tree = etree.ElementTree(root)
tree.write('text.xml',xml_declaration=True,encoding='utf-8')
0 голосов
/ 04 мая 2012

В дополнение к MRAB ответьте на несколько строк кода:

import codecs
from lxml import etree

root = etree.Element('root')
sect = etree.SubElement(root,'sect')

# do some other xml building here

with codecs.open('test.xml', 'w', encoding='utf-8') as f:
    f.write(etree.tostring(root, encoding=unicode))
...