2

我一直在为海地 (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 终端时):

mwen bezwen 㨠d medikal

  1. 那是什么编码?它是双重编码的字符串吗?
  2. 我如何“修复它”使其可渲染?
  3. 以这种方式打印是因为我缺少字体或其他东西吗?

Python chardet库说:

{'confidence': 0.93812499999999999, 'encoding': 'utf-8'}

但是,Python,当我运行 string/unicode/codecs decode 时,我得到了旧的:

UnicodeDecodeError:“ascii”编解码器无法解码位置 30 中的字节 0xc3:序数不在范围内(128)

哦,Python 将相同的字符串打印到标准输出中。

调用会打印以下内容:' mwen repr()bezwen \xc3\xa3 \xc2\xa8 d medikal '

4

3 回答 3

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'
>>>

更新:

如果(正如 AN Other 暗示的那样)您让程序包随机选择输出语言,并且您怀疑它的选择是韩语(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信息流很有趣:“一个字符串处理应用程序”->“一个统计语言翻译系统”->“一个机器翻译系统(开源/免费软件)在海地提供帮助(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

从谷歌翻译(alpha)微软翻译(beta)
Mwen bezwen èd medikal获得的测试 2 :。
第三个单词是带有 GRAVE (U+00E8) 后跟“d”的拉丁小写字母 E。

更新 3

你说“”“输入:utf8(也许,我认为我的几个文件中可能有不正确的编码文本)“””

假设(您从未明确说明过)您的所有文件都应以 UTF-8 编码:

对齐的 en-fr-ht 语料库的 zip 文件有几个文件在尝试将它们解码为 UTF-8 时崩溃。

发生这种情况的诊断:

chardet 没用(在这种情况下);它迷惑了很长时间,并以 80 到 90 pct 的置信度对 ISO-8859-2 (东欧 aka Latin2) 进行猜测。

下一步:选择 ht-en 目录(ht 使用的重音字符比 fr 少,因此更容易看到发生了什么)。

预期:e-grave 是假定良好的 ht 文本(网站、CMU 文件)中最常见的非 ASCII 字符……大约是下一个 o-grave 的 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

前 2 行解释为

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) 为什么 Moses 不抱怨非 UTF-8 输入?可能性:(1)它正在处理原始字节,即它不转换为 Unicode(2)它尝试转换为 Unicode,但默默地忽略失败:-(

于 2010-02-23T21:37:44.260 回答
1

看起来您的默认编码是 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 脚本,并且可能会产生意想不到的副作用。

于 2010-02-23T18:03:13.897 回答
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

这似乎确实是您的图书馆给您垃圾的情况,无论是否垃圾。

于 2010-02-23T21:27:18.667 回答