Unicode: вывод файла Python/lxml не соответствует ожиданиям (печать или запись)

Я разбираю файл xml, используя приведенный ниже код:

import lxml

file_name = input('Enter the file name, including .xml extension: ')
print('Parsing ' + file_name)

from lxml import etree

parser = lxml.etree.XMLParser()


tree = lxml.etree.parse(file_name, parser)
root = tree.getroot()

nsmap = {'xmlns': 'urn:tva:metadata:2010'} 


with open(file_name+'.log', 'w', encoding='utf-8') as f:
    for info in root.xpath('//xmlns:ProgramInformation', namespaces=nsmap):
       crid = (info.get('programId'))
       titlex = (info.find('.//xmlns:Title', namespaces=nsmap))
       title = (titlex.text if titlex != None else 'Missing')
       synopsis1x = (info.find('.//xmlns:Synopsis[1]', namespaces=nsmap))             
       synopsis1 = (synopsis1x.text if synopsis1x != None else 'Missing')               
       synopsis1 = synopsis1.replace('\r','').replace('\n','')
       f.write('{}|{}|{}\n'.format(crid, title, synopsis1))    

Возьмем, к примеру, название «Přešité bydlení». Если я напечатаю заголовок во время разбора файла, он выйдет, как и ожидалось. Однако, когда я пишу это, оно отображается как «PÅ™eÅ¡ité bydlenû.

Я понимаю, что это связано с кодировкой (поскольку я смог изменить команду печати, чтобы использовать UTF-8, и «испортить» вывод), но я не смог распечатать письменный вывод так, как хотел. Я просмотрел библиотеку кодеков, но не смог. Наличие 'encoding = "utf-8"' в строке синтаксического анализатора XML не имело никакого значения.

Как я могу настроить письменный вывод, чтобы он был удобочитаемым для человека?


person Nick    schedule 03.04.2014    source источник
comment
Что вы используете для проверки вывода файла?   -  person Alastair McCormack    schedule 04.04.2014


Ответы (2)


У меня раньше были всякие неприятности с этим. Но решение довольно простое. В разделе документация. Этот разговор о Python также очень полезен для понимания проблемы. Юникод может быть болью. Однако становится намного проще, если вы начнете использовать Python 3.

import codecs
f = codecs.open('test', encoding='utf-8', mode='w+')
f.write(u'\u4500 blah blah blah\n')
f.seek(0)
print repr(f.readline()[:1])
f.close()
person Jonathan    schedule 03.04.2014
comment
Просто чтобы сделать это более очевидным для других людей, 4500 в кавычках необходимы, чтобы заставить его работать. Мне не нужно/использовать f.seek(0) в моем приложении. - person Nick; 03.04.2014
comment
Я говорил слишком рано. Я видел много '?' в тексте, где он не может отображать символы. Например, он выводит «nikdo a nic nám neuteče» вместо «nikdo a nic nám neuteče». Любые идеи? - person Nick; 03.04.2014
comment
\u4500 - персонаж хань и не имеет ничего общего с вопросом ОП. Этот блок кода скопирован из руководства Python и не имеет значения. - person Alastair McCormack; 04.04.2014

Ваш код выглядит нормально, поэтому я считаю, что ваш ввод неверен. Предполагая, что вы просматриваете свой выходной файл с помощью средства просмотра или оболочки UTF-8, я подозреваю, что кодировка в <?xml не соответствует фактической кодировке.

Это объясняет, почему печать работает, но не записывается в файл. Если ваша оболочка/IDE установлена ​​на «ISO-8859-2», а ваш входной XML также «ISO-8859-2», тогда печать выталкивает необработанную кодировку.

person Alastair McCormack    schedule 03.04.2014
comment
Похоже, это проблема с «Текстпадом», который не поддерживает должным образом UTF-8 (используется только потому, что он отлично подходит для открытия действительно больших файлов журналов). Он корректно открывается в Notepad++ и все в мире хорошо. - person Nick; 04.04.2014