我一直致力于海地统计翻译系统(code.google.com/p/ccmts),它使用C ++后端(http://www.statmt.org/moses/?n=Development.GetStarted),Python驱动C ++引擎/后端。
我已经将UTF-8 Python字符串传递给C ++ std::string
,完成了一些处理,将结果返回到Python中,这里是字符串(从C ++打印到Linux终端时):
Python chardet库说:
{'confidence': 0.93812499999999999, 'encoding': 'utf-8'}
但是,Python,当我运行一个字符串/ unicode / codecs解码时,给了我旧的:
UnicodeDecodeError:'ascii'编解码器无法解码位置30的字节0xc3:序数不在范围内(128)
哦,Python将相同的字符串打印到标准输出中。
repr()
来电打印以下内容:'mwen bezwen \ xc3 \ xa3 \ xc2 \ xa8 d medikal'
答案 0 :(得分:3)
看起来像是垃圾进出,垃圾出来的情况。以下是有关如何查看数据中的内容的一些线索。 repr()
和unicodedata.name()
是您的朋友。
>>> s = ' mwen bezwen \xc3\xa3 \xc2\xa8 d medikal '
>>> print repr(s.decode('utf8'))
u' mwen bezwen \xe3 \xa8 d medikal '
>>> import unicodedata
>>> unicodedata.name(u'\xe3')
'LATIN SMALL LETTER A WITH TILDE'
>>> unicodedata.name(u'\xa8')
'DIAERESIS'
>>>
更新
如果(正如A.N.其他暗示的那样)你让包随机选择输出语言,你怀疑它的选择是例如韩语(a)告诉我们(b)尝试使用与该语言相关的编解码器解码输出....这里不仅有韩语,还有中文,日文和俄文两种:
>>> s = ' mwen bezwen \xc3\xa3 \xc2\xa8 d medikal '
>>> for enc in 'euc-kr big5 gb2312 shift-jis euc-jp cp1251 koi8-r'.split():
print enc, s.decode(enc)
euc-kr mwen bezwen 찾 짢 d medikal
big5 mwen bezwen 瓊 穡 d medikal
gb2312 mwen bezwen 茫 篓 d medikal
shift-jis mwen bezwen テ」 ツィ d medikal
euc-jp mwen bezwen 達 即 d medikal
cp1251 mwen bezwen ГЈ ВЁ d medikal
koi8-r mwen bezwen цё б╗ d medikal
>>>
没有非常合理,真的,尤其是koi8-r。进一步的建议:检查你接口的包的文档(URL请!)...它对编码有什么看法?在你尝试两种语言之间? “mwen bezwen”在预期的输出语言中是否有意义?尝试更大的文本样本 - chardet是否仍然表示UTF-8?是否有任何较大的输出在预期的输出语言中有意义?尝试将英语翻译成仅使用ASCII的另一种语言 - 您是否获得了有意义的ASCII输出?您是否愿意透露您的Python代码和swig接口代码?
更新2 信息流很有趣:“字符串处理应用” - > “统计语言翻译系统” - > “在海地提供帮助的机器翻译系统(opensource / freesoftware)(crisiscommons.org)”
请尝试通过以下事实替换“未知”:
Input language: English (guess)
Output language: Haitian Creole
Operating system: linux
Python version: unknown
C++ package name: unknown
C++ package URL: unknown
C++ package output encoding: unknown
Test 1 input: unknown
Test 1 expected output: unknown
Test 1 actual output (utf8): ' mwen bezwen \xc3\xa3 \xc2\xa8 d medikal '
[Are all of those internal spaces really in the string?]
Test 2 input: 'I need medical aid.'
Test 2 expected output (utf8): 'Mwen bezwen \xc3\xa8d medikal.'
Test 2 actual output (utf8): unknown
从Google Translate (alpha)和Microsoft Translate (beta)获得的测试2
{{3}}:
Mwen bezwen èd medikal
。
第三个单词是LATIN SMALL LETTER E,带有GRAVE(U + 00E8),然后是'd'。
更新3
你说“”“输入:utf8(也许,我认为我的一些文件可能有不正确的文字编码)”“”
假设(您从未明确说明)所有文件都应以UTF-8编码:
对齐的en-fr-ht语料库的zip文件有几个文件在尝试将它们解码为UTF-8时崩溃。
诊断为何会发生这种情况:
chardet没用(在这种情况下);它很长一段时间,并回来猜测ISO-8859-2(东欧又名Latin2),信心水平为80到90%。下一步:选择ht-en目录(ht使用较少的重音字符而不是fr,因此更容易看到发生了什么)。
期望:电子坟墓是推测良好的ht文本(网站,CMU文件)中最常见的非ASCII字符...大约是下一个o-grave的3倍。第3个最常见的是在噪音中丢失。
获取文件hten.txt中的非ascii字节数。前5名:
8a 99164
95 27682
c3 8210
a8 6004
b2 2159
最后三行由
解释e-grave is c3 a8 in UTF-8
o-grave is c3 b2 in UTF-8
2159 + 6004 approx == 8210
6004 approx == 3 * 2159
前两行由
解释e-grave is 8a in old Western Europe DOS encodings like cp850!!
o-grave is 95 in old Western Europe DOS encodings like cp850!!
99164 approx == 3 * 27682
包含latin1或cp1252的说明不含水(8a是latin1中的控制字符; 8a是cp1252中的S-caron)。
检查内容显示该文件是多个原始文件的集合,一些UTF-8,至少一个cp850(或类似)。罪魁祸首似乎是圣经!!!
编码的混合解释了为什么chardet正在挣扎。
建议:
(1)实现对所有输入文件的编码检查。确保它们在前面转换为UTF-8,就像在边界控制时一样。
(2)在发布之前实现脚本以检查UTF-8可解码性。
(3)圣经文本的拼写(一目了然)与网站的拼写不同(更多的撇号)。您可能希望与您的克里奥尔语专家讨论您的语料库是否因不同的拼写错误而被扭曲......还有一些问题;你是否希望大量使用无酵饼和麻布?骨灰?请注意,cp850的内容约占集团总数的90%;有些圣经可能没事,但90%似乎超过了顶层。
(4)为什么摩西不抱怨非UTF-8输入?可能性:(1)它正在处理原始字节,即它不转换为Unicode(2)它尝试转换为Unicode,但默默地忽略失败: - (
答案 1 :(得分:1)
您的default encoding似乎是ASCII。
您可以显式转换您的unicode字符串:
print u"Hellö, Wörld".encode("utf-8")
或者,如果要在脚本中全局更改它,请将sys.stdout替换为将其编码为utf-8的包装器:
import sys, codecs
sys.stdout = codecs.EncodedFile(sys.stdout, "utf-8")
print u"Hellö, Wörld!"
此外,您可以通过sys.setdefaultencoding一次性更改默认编码(网站范围内),但这只能在sitecustomize.py中完成。我不会这样做,但是 - 看起来很方便,它会影响你系统上的所有python脚本,并且可能会产生意想不到的副作用。
答案 2 :(得分:1)
编辑:没关系我之前发布过的垃圾;这是错的。
正如其他人所建议的,这将在python中获得正确的unicode对象,假设它的意思是utf-8:
>>> ' mwen bezwen \xc3\xa3 \xc2\xa8 d medikal '.decode('utf-8')
u' mwen bezwen \xe3 \xa8 d medikal '
>>> print _
mwen bezwen ã ¨ d medikal
这似乎确实是你的图书馆给你带来垃圾的情况,无论垃圾进入与否都是垃圾。