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 个回答
f1.write(' '.join(list1))
此时,list1
里包含的是 Unicode 字符串。你不能直接把 Unicode 写入文件,因为文件是以字节的形式来处理的。你应该明确地进行编码,比如用 (' '.join(list1).encode('utf-8'))
,或者像 Ignacio 建议的那样,使用 codecs
这个工具,它可以自动帮你把 Unicode 字符串转换成字节。现在你定义了一个变量 CODEC
,但还没有使用它。
你确定要去掉所有的连字符(-)吗?从你的输入文件来看,所有的替换都是两个或三个字符的代码,比如说 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' 这样的翻译在字典中缺失。我不懂印地语,但谷歌翻译给出的某些英文单词和你的翻译一致,所以我觉得我在正确的方向上。
-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*यै हुआ"
除了你提到的问题之外,还有一些其他问题。
(1) 概念问题:“E-k- b-u-d-z*dhi-m-aan- p-ksii#” 并不是 “英语”。这是用ASCII编码的印地语,使用了一种罗马化的方案。它看起来像ITRAN,但ITRAN没有AA和A,只有aa和a。这个方案有名字吗?能提供一个网址吗?你要描述的对象更准确的说法是“将一些印地语文本从未命名的罗马化转换为天城文”。
(2) 将你的文本从印地语翻译成英语的结果(比如“A WISE OLD BIRD”等)只有中等的实用性。预期的天城文输出会更好。
(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*धिमैन पक्षी
一个浓密的森林里有一棵高大的树,上面长满了树枝,像是被三只鸟围绕着。它们在树上栖息,安全又舒适。它们中有一只非常聪明的鸟。有一天,这只聪明的鸟看到树根下有一条小蛇,便和其他鸟讨论:“你们看到了那条小蛇吗?”它问道:“你们应该把它赶走。”
“为什么要赶走它?”其他鸟惊讶地问,“它那么小,我们怎么可能抓住它?”
“我的朋友们,”聪明的鸟回答,“那条小蛇很快就会长大,它会爬上树,缠住我们,然后变得又粗又强壮。”
“那又怎么样?”
这段文字在用谷歌翻译时只有几个可识别的单词。
更新 在更仔细检查音译表后:
三个条目(AA、II和U)在天城文对应字符后面有一个空格。也许应该去掉这些空格。
辅音的一般模式似乎是:
天城文字母XA用x表示
天城文字母XXA用X表示
天城文字母XHA用xh表示
天城文字母XXHA用Xh表示
然而,有3个条目打破了这个模式:
SSA -> sha,但模式说是S
TA -> th,但模式说是t
THA -> tha,但模式说是th
注意:更改上述3个条目后,我的代码不再抱怨S和t在音译你的示例文本时未被更改,并且去掉了看似异常的sha和tha条目。
条目(D和dr)映射到同一个字符,天城文字母DDA。D是该字符的预期条目;也许dr应该映射到其他地方。
没有天城文字母NGA(U+0919)的条目;也许它应该编码为ng——在示例文本中有几个以ng结尾的单词。
示例文本中的“z*”出现与天城文字母ZA(U+095B)有关吗?