如何在Python 2.6中添加新的编码?

4 投票
1 回答
979 浏览
提问于 2025-04-17 16:11

又遇到一个编码问题,我正在处理一个使用IBM870编码的IBM大型机,而这个编码在Python或者其他任何地方都不被支持。

幸运的是,有位天才程序员写了一个脚本,可以为Python生成合适的编码定义,这些定义是基于在FileFormat.info上找到的字符列表。

使用的字符列表可以在这里找到:IBM870字符列表

生成的编码可以在这里查看:cp870.py

这个系统是运行在RHEL 6.3上的,使用的是Python 2.6:

Python 2.6.6 (r266:84292, Aug 28 2012, 10:55:56) 
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2

cp870.py文件放在:

/usr/lib64/python2.6/encodings/

以下条目已被添加到:

/usr/lib64/python2.6/encodings/aliases.py

# cp870 codec
'870'                : 'cp870',
'csibm870'           : 'cp870',
'ibm870'             : 'cp870',

别名被正确解析,如这里所示(感谢这个回答):

>>> from encodings.aliases import aliases
>>> def find(q):
...     return [(k,v) for k, v in aliases.items() if q in k or q in v]
... 
>>> find('870')
[('ibm870', 'cp870'), ('870', 'cp870'), ('csibm870', 'cp870')]
>>> find('cp870')
[('ibm870', 'cp870'), ('870', 'cp870'), ('csibm870', 'cp870')]
>>> find('ibm870')
[('ibm870', 'cp870'), ('csibm870', 'cp870')]

当我尝试对一些字符使用encode()时,结果并没有按预期工作:

>>> 'c'.encode('cp870')
'\x83'
>>> 'č'.encode('cp870')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/encodings/cp870.py", line 12, in encode
    return codecs.charmap_encode(input,errors,encoding_table)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)

根据cp870.py,'\x83'应该是这样的:

u'\x83'     #  0x23 -> NO BREAK HERE (U+0083)

由于我对Python还是个新手,能否请教一下,还需要什么才能让Python正确加载和使用这个编码?

1 个回答

3

在Python 2.x中,Unicode字符串需要加上uU的前缀。如果没有这个前缀,字符串就被认为是ASCII编码(或者其他8位编码)。

另外,Python默认你输入的内容是ASCII编码的(虽然你可以设置其他编码)。所以,当你在引号里放入一个非ASCII字符时,解释器会尝试把它当作ASCII来解码,这就会导致你看到的错误。

因此,你需要加上u前缀,并使用转义序列来指定这个字符:

U'\x83'.encode('cp870')

撰写回答