Python - кодек, кодирующий ascii в unicode: ошибка

:) Я пытаюсь вернуться к процессу возврата транслитерации входного файла (в настоящее время на английском языке) к его первоначальному виду (на хинди)

Образец или часть входного файла выглядит следующим образом:

E-k- b-u-d-z*dhi-m-aan- p-ksii#

E-k- ghn-e- j-ngg-l- m-e-ng E-k- b-h-u-t- UUNNc-aa p-e-dr thaa#
U-s- k-ii p-t-z*t-o-ng s-e- l-d-ii shaakhaay-e-ng m-j-*zb-uut- b-aaj-u-O-ng k-ii t-r-h- pheil-ii h-u-II thiing#
w-n- h-NNs-o-ng k-aa E-k- jhu-nhz*D- I-s- p-e-dr p-r- n-i-w-aas- k-r-t-aa thaa#
w-e- s-b- y-h-aaNN s-u-r-ksi-t- the- AUr- b-dre- AAr-aam- s-e- r-h-t-e- the-#
U-n- m-e-ng s-e- E-k- p-ksii b-h-u-t- b-u-d-z*dhi-m-aan- thaa#
I-s- b-u-d-z*dhi-m-aan- p-ksii n-e- E-k- d-i-n- p-e-dr k-ii j-dr m-e-ng s-e- E-k- l-t-aa k-o- U-g-t-e- d-e-khaa# 
I-s- k-e- b-aar-e- m-e-ng U-s-n-e- d-uus-r-e- p-ksi-y-o-ng s-e- b-aat- k-ii#
"k-z*y-aa t-u-m-z*h-e-ng w-h- l-t-aa d-i-khaaII d-e-t-ii h-ei", U-s- n-e- U-n- s-e- p-uuchaa "t-u-m-z*h-e-ng I-s-e- n-Shz*T- k-r- d-e-n-aa c-aah-i-E-"#
"I-s-e- k-z*y-o-ng n-Shz*T- k-r- d-e-n-aa c-aah-i-E-?" h-NNs-o-ng n-e- AAshz*c-*ry- s-e- p-uuchaa "y-h- t-o- I-t-n-ii cho-T-ii s-e- h-ei#
h-m-e-ng y-h- k-z*y-aa h-aan-i- p-h-u-NNc-aa s-k-t-ii h-ei"#
"m-e-r-e- m-i-tro-ng," b-u-d-z*dhi-m-aan- p-ksii n-e- U-t-z*t-r- d-i-y-aa "w-h- cho-T-ii s-ii l-t-aa j-l-z*d-ii h-ii b-drii h-o- j-aay-e-g-ii#
y-h- h-m-aar-e- p-e-dr p-r- c-Dh*z k-r- U-s- s-e- l-i-p-T-t-ii j-aay-e-g-ii AUr- phi-r- m-o-T-ii AUr- m-j-*zb-uut- h-o- j-aay-e-g-ii"#
"t-o- k-z*y-aa h-u-AA"#

Его эквивалентное значение на английском языке:

A WISE OLD BIRD.

Deep in the forest stood a very tall tree.
Its leafy branches spread out like long arms.
This was the home of a flock of wild geese.
They were safe there.
One of the geese was a wild old bird.
One  day this wise old bird noticed  a small creeper growing at the foot of the tree.
He spoke to the other birds about it.
"Do you see that creeper ?" he said to them.
"You must destroy it."
"Why must we destroy it ?" asked the geese in surprise.
"It is so small.
What harm can it do?"
"My friends," replied the wise old bird, " that little creeper will soon grow.

Мой сценарий выглядит так:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import sys
CODEC = 'utf-8'
input_file=sys.argv[1]
output_file=sys.argv[2]
list1=[]



f=open(input_file,'r')
f1 = open(output_file,'w')

english_hindi_dict={'A' : u'अ' ,  'AA' : u'आ ' , 'I' : u'इ' , 'II' : u'ई ' , 'U' : u'उ ' ,\
                'UU' : u'ऊ' , 'r' : u'ऋ' , 'E' : u'ए' , 'ai' : u'ऐ' , 'O' : u'ओ' , 'AU' : u'औ' ,\
                'k' : u'क' , 'kh' : u'ख' , 'g' : u'ग' , 'gh' : u'घ' , 'c' : u'च' , 'ch' : u'छ',\
                'j': u'ज' , 'jh' : u'झ' , 'tr' : u'त्र' , 'T' : u'ट'  , 'Th' : u'ठ' , 'D' : u'ड',\
                'dr' : u'ड' , 'Dh' : u'ढ' , 'Na' : u'ण' , 'th' : u'त' ,  'tha' : u'थ',\
                'd' : u'द' , 'dh': u'ध' , 'n' : u'न' , 'p' : u'प' , 'ph' : u'फ' ,\
                'b' : u'ब' , 'bh' : u'भ' , 'm' : u'म' , 'y' : u'य' , 'r' : u'र' , 'l' : u'ल' ,\
                'w' : u'व' , 'sh' : u'श' , 'sha' : u'ष', 's' : u'स' , 'h' : u'ह' , 'ks' : u'क्ष' ,\
                'i' : u'ि' , 'ii' : u'ी' , 'u' : u'ु' , 'uu' : u'ू' , 'e' : u'े' ,\
                'aa' : u'ै' , 'o' : u'ो' , 'AU' : u'ौ' ,'H' : u'्' ,'mn' : u'ं' ,\
                'NN' : u'ँ' , 'AW' : u'ॅ' , 'rr' : u'ृ' , '4' : u'४' , '6': u'६'  , '8' : u'८',\
                '2' : u'२' , '5' : u'५' , '3' : u'३' , '7' : u'७' , '9' : u'९' , '1' : u'१'}
for line in f:
      #line=line.strip() to remove a line from its newline character....  
      #line=line.rstrip('.')   
      line=line.replace('-','')
      line=line.replace('#','|') # i am using the or symbol for poornviram
      #line=line.replace('।','')
      #line = line.lower()
for word in line:
    for ch in word:
        if (ch in english_hindi_dict) :
            translatedToken = english_hindi_dict[ch]
        else :
                translatedToken = ch

#{ translatedToken = english_hindi_dict[ch] }

#for ch in line:
    f1.write(translatedToken)
    #print translatedToken
    #line = line.replace( char,english_hindi_dict[char] )   
      #list1.append(line)
f.close()

f1.write(' '.join(list1))

f1.close()

ошибка, которую я получаю:

python transliterate_eh_nw.py Hstory.txt op1.txt
Traceback (most recent call last):
  File "transliterate_eh_nw.py", line 43, in <module>
    f1.write(translatedToken)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u092f' in position 0: ordinal not in range(128)

Подскажите, пожалуйста, как мне справиться с этой ошибкой. Спасибо..:)

3 ответа

Решение

У вас есть несколько проблем, кроме той, о которой вы спрашивали.

(1) Концептуальная проблема: "Ek- budz*dhi-m-aan- p-ksii#" не является "английским". Это язык хинди, написанный на ASCII с использованием некоторой схемы латинизации. Похоже, что ITRAN, но у ITRAN нет AA и A, у него есть только aa и a. У схемы есть имя? Можете ли вы предоставить URL? Ваш объект лучше описать как "транслитерацию некоторого текста на хинди из безымянной латинизации в сценарий деванагари".

(2) Отображение результата перевода вашего текста с хинди на английский ("Мудрое старое животное" и т. Д.) Является лишь умеренно полезным. Ожидаемый результат Деванагари был бы лучшей идеей.

(3) Как отметил @kaiser.se, словарь транслитерации имеет многобайтовые (до 3 байтов!) Ключи, некоторые из которых являются префиксами других. предположительно AA должны быть признаны в приоритетном A, gh должен быть признан до g и т. д. Итерации по элементам словаря происходят в порядке, который предсказуем, но для ваших целей должен рассматриваться как случайный. В следующем коде я отдает приоритет более длинным "ключам".

(4) Либо в словаре отсутствуют некоторые буквенные ключи (S t z), либо правила транслитерации сложнее, чем кто-либо из нас догадывался

(5) Значение символов # * и - не на 100% очевидно. Из введенного вами текста видно, что z и * отображаются только в комбинации как z *

(6) Было бы неплохо, если бы вы объяснили shaakhaay-e-ng... это начинается с sh затем aa или это начинается с sha затем a? Каковы правила?

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

Вот некоторый код:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

input_data = """
E-k- b-u-d-z*dhi-m-aan- p-ksii#

E-k- ghn-e- j-ngg-l- m-e-ng E-k- b-h-u-t- UUNNc-aa p-e-dr thaa#
[snip]
"t-o- k-z*y-aa h-u-AA"#
"""

roman_devanagari_dict={'A' : u'अ' ,  'AA' : u'आ ' , 'I' : u'इ' , 'II' : u'ई ' , 'U' : u'उ ' ,\
[snip]
            '2' : u'२' , '5' : u'५' , '3' : u'३' , '7' : u'७' , '9' : u'९' , '1' : u'१'}

#Presuming we need to do the 3-letter cases then the 2-letter then the 1-letter
replacements = [(-len(k), unicode(k), v) for k, v in roman_devanagari_dict.items()]
replacements.sort()

data = input_data.decode('ascii')

for _junk, from_text, to_text in replacements:
    data = data.replace(from_text, to_text)

# Presuming the '-' are inter-character markers, delete them last, not first
data = data.replace(u'-', '')
data = data.replace(u'#', '')
print "untransliterated:", set(c for c in data if 0x20 < ord(c) < 0x7f)

BOM = u'\ufeff'
outf = open('devanagari.txt', 'w')
outf.write(BOM.encode('utf8')) # for the benefit of clueless Windows s/w
outf.write(data.encode('utf8'))
outf.close()

Выход:

बुद बुदz*धिमैन पक्षी

बहु घने जनगगल एक बहु बहु बहु थ z z z z z z z z z z z z z z z z z z सब सब सब सब सब सब सब सब सब सब सब बहु मेनग से एक बहु बहु बुद धिमैन धिमैन हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेि हेियै T स ने उ न से पूछै "т ु г हेनग इसे नSह г ट कर देनै चैहिए" "इसे क г योनग नSह г ट कर देनै चैहिए?" श ने आ शरय से पूछै पूछै यह यह ो पूछै पूछै दियै जल जल जल क क क जल जल जल जल जल जल जल जल जल ै ै ै जल जल जल जल "पर चढ z कर स स से लिपट लिपटtी जैयेगी ौर फिर मोटी मज मज z बू t हो" "" t ो क z यै t "

который имеет только несколько узнаваемых слов, когда толкнул через Google Translate.

Обновите после более тщательного изучения таблицы транслитерации:

  • Три записи (AA, II и U) имеют пробел после эквивалента Деванагари. Возможно, пробелы должны быть удалены.

  • Общая схема для согласных выглядит так:

ПИСЬМО DEVANAGARI XA обозначается как x
Письмо Деванагари XXA представлено знаком X
ПИСЬМО DEVANAGARI XHA представлено xh
Письмо Деванагари XXHA представлено Xh

Однако 3 записи нарушают схему:
SSA -> ша, но шаблон говорит S
TA -> но шаблон говорит т
THA -> но шаблон говорит, что

Примечание: изменение вышеуказанных 3 записей остановило мой код от жалоб на то, что S и t были оставлены без изменений при транслитерации вашего образца текста, и удалило, казалось бы, аномальные записи sha и tha.

  • Записи (D и dr) сопоставляются с одним и тем же символом, DEVANAGARI LETTER DDA. D - ожидаемая запись для этого символа; возможно, доктор должен быть нанесен на карту в другом месте.

  • Там нет записи для DEVANAGARI LETTER NGA (U+0919); возможно, он должен быть закодирован как ng - в образце текста есть несколько слов, оканчивающихся на ng.

  • Имеют ли вхождения в строку "z*" в тексте образца какое-либо отношение к DEVANAGARI LETTER ZA (U+095B)?

Вы уверены, что хотите удалить все дефисы (-)? Глядя на ваш входной файл, кажется, что все замены представляют собой двух- или трехсимвольные коды, такие как u'I - ':u'इ'. Если это так, вы можете сделать что-то вроде ниже, но убедитесь, что вы используете строки Unicode для всех ваших ключей и значений в словаре:

import codecs

# read the whole file at once
f = codecs.open(input_file,'r','ascii')
data = f.read()
f.close()

# perform all the replacements
for k,v in english_hindi_dict.items():
    data = data.replace(k,v)

# write the whole file result
f = codecs.open(output_file,'w',CODEC)
f.write(data)
f.close()

Следуя этой теории, я получил следующий результат, который выглядит как переводы, такие как "z*", "t-", "ng" и "ei", отсутствуют в словаре. Я не читаю хинди, но Google Translate предложил некоторые из английских слов в вашем переводе, поэтому я думаю, что я на правильном пути.

-z*धिमैन पक्षी

एक घने जngगल मेng एक बहुt- ऊँचै पेड तै
उस की पt-z*t-ोng से लदी शैखैयेng मज*zबूt- बैजुओng की t-रह फeiली हुई तीng
वन हँसोng कै एक झुnhz*ड इस पेड पर निवैस करt-ै तै
वे सब यहैँ सुरक्षिt- ते ौर बडे आरैम से रहt-े ते
उन मेng से एक पक्षी बहुt- बुदz*धिमैन तै
इस बुदz*धिमैन पक्षी ने एक दिन पेड की जड मेng से एक लt-ै को उगt-े देखै 
इस के बैरे मेng उसने दूसरे पक्षियोng से बैt- की
"कz*यै t-ुमz*हेng वह लt-ै दिखैई देt-ी हei", उस ने उन से पूछै "t-ुमz*हेng इसे नShz*ट कर देनै चैहिए"
"इसे कz*योng नShz*ट कर देनै चैहिए?" हँसोng ने आशz*च*rय से पूछै "यह t-ो इt-नी छोटी से हei
हमेng यह कz*यै हैनि पहुँचै सकt-ी हei"
"मेरे मित्रोng," बुदz*धिमैन पक्षी ने उt-z*t-र दियै "वह छोटी सी लt-ै जलz*दी ही बडी हो जैयेगी
यह हमैरे पेड पर चढ*z कर उस से लिपटt-ी जैयेगी ौर फिर मोटी ौर मज*zबूt- हो जैयेगी"
"t-ो कz*यै हुआ"

f1.write(' '.join(list1))

list1На данный момент содержит строки Unicode. Вы не можете писать Unicode напрямую в файл, это байтовый интерфейс. Вы должны либо закодировать это явно (' '.join(list1).encode('utf-8'))или, как предлагает Игнасио, использовать codecs Обертка для неявного кодирования строк Unicode, которые вы отправляете в нее. На данный момент вы определяете переменную CODEC, но ничего не делать с этим.

Другие вопросы по тегам