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 Parser не направи никаква разлика.

Как мога да конфигурирам писмения изход да бъде четим от хора?


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


Отговори (2)


Имах всякакви проблеми с това преди. Но решението е доста просто. Има глава за това как да четете и пишете в unicode във файл в документация. Този разговор за Python също е много поучителен за разбиране на проблема. Unicode може да бъде болка. Става много по-лесно, ако започнете да използвате 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 е герой Хан и няма нищо общо с въпроса на OP. Този кодов блок е копиран от ръководството на Python и е без значение - person Alastair McCormack; 04.04.2014

Вашият код изглежда добре, така че смятам, че въвеждането ви е глупаво. Ако приемем, че преглеждате изходния си файл с UTF-8 viewer или shell, тогава подозирам, че кодирането в <?xml не съвпада с действителното кодиране.

Това би обяснило защо печатането работи, но не и записът във файл. Ако вашата обвивка/IDE е настроена на "ISO-8859-2" и вашият входен XML също е "ISO-8859-2", тогава отпечатването изтласква необработеното кодиране.

person Alastair McCormack    schedule 03.04.2014
comment
Изглежда, че има проблем с „Textpad“, който не поддържа правилно UTF-8 (използва се само защото е страхотен за отваряне на наистина големи регистрационни файлове). Отваря се правилно в Notepad++ и всичко на света е наред. - person Nick; 04.04.2014