根据代码页 437 的维基百科页面,字节值
\x01
到 \x1f
应解码为图形字符,例如b'\x01'
等于 ☺ '\u263A'
。但这不是 decode
产生的:
>>> b'\x01'.decode('cp437')
'\x01'
Python 3.6 是这样,但 2.7 对于所有 31 字节值也是如此。
虽然存在与字节范围
\x01
到 \x1f
相关的图形,但这些图形仅在某些上下文中使用。在其他上下文中,这些代码点将被解释为控制字符,如 ASCII 中那样。引用 CP437 上的 IBM 页面:
代码点 X'01' 到 X'1F' 和 X'7F' 可能是控件或图形,具体取决于上下文。显示内存映射中的十六进制代码 视频显示缓冲区是一个图形。对于打印机,图形上下文是由数据流中的前面的控制序列建立的。那里有两个 这样的控制序列:ESC X'5C'和ESC X'5E'分别命名为“打印所有字符”和“打印单个字符”。其他情况下的代码 有问题的点用作对照。
Python 的 CP437 解码基于 Unicode.org 上的 Unicode 映射,它使用控制字符解释。
Unicode 常见问题解答意味着“CP437 和其他 DOS 类型代码页的特殊图形字符(01-1F、7F)的正确 Unicode 映射”应在 https://www.unicode.org/ 上提供Public/MAPPINGS,但深入挖掘只会发现带有控制字符的映射,以及链接到几个 IBM 网站的 page。深入研究 IBM 的站点会发现 ftp://ftp.software.ibm.com/software/globalization/gcoc/attachments/CP00437.txt,它根据 IBM 的
GCGID 给出了
\x01
-
\x1f
的图形映射系统,但不是 Unicode。
我不知道是否真的有is来自IBM或Unicode的官方映射,它根据CP437的图形解释给出了
\x01
-\x1f
的规范Unicode映射。
我设法在那里找到这个文件:
https://unicode.org/Public/MAPPINGS/VENDORS/MISC/IBMGRAPH.TXT
它包括 Unicode 字符 (0x01-0x1f) 到 IBM CP437 以及 IBM CP864(阿拉伯语)的映射。
是的,它坏了。
不,还没有人将此作为错误提交给 PSF。可能没有人会这样做,原因有二:
首先,有几个不明确的字符(确切地说,Microsoft 没有实现“IBM Codepage 437”),并且 PSF 可能不愿意对其中任何一个做出决定:
b'\x07'
代表 Bell 或 Bulletb'\x08'
代表退格键或倒转项目符号b'\x09'
代表水平制表符或白色圆圈b'\x0a'
代表回车或反白圆圈b'\x0d'
代表换行或八分之一音符/音乐音符其次,代码页 437 现在实际上从未被使用过,因为 CPython 3.6 在 Windows 上添加了一个不可见的 UTF-16 控制台 I/O。 如果您想将代码页
x-microsoft-437
type
一起使用时可以正确呈现的文本文件,或者在 Windows 上的 PyPy 上执行 Unicode I/O),这里有一个保守的方法代码片段(它将所有 5 个不明确的字符实现为控制字符,这正是 Windows CMD 实现它的方式)您可以添加到您自己的代码中:"""https://stackoverflow.com/questions/46942721"""
# -*- filename: _site_codecs/x_microsoft_437.py -*-
# Remember that sys.stdin.reconfigure() cannot be called after any input has been read
# So if you're using this for I/O, please call that ONLY in __main__ after appropriate checks
# https://stackoverflow.com/questions/77808931
import codecs
import encodings
from encodings import cp437 as _psf_cp437
def _cp437_search_function(encoding):
if encodings.normalize_encoding(encoding) == encodings.normalize_encoding(_Cp437CodecInfo.name):
return _Cp437CodecInfo
return None
codecs.register(_cp437_search_function)
class _Cp437Codec(codecs.Codec):
# https://github.com/python/cpython/blob/v3.12.1/Lib/encodings/cp437.py#L9
def encode(self,input,errors='strict'):
return codecs.charmap_encode(input,errors,_cp437_encoding_map)
def decode(self,input,errors='strict'):
return codecs.charmap_decode(input,errors,_cp437_decoding_map)
class _Cp437IncrementalEncoder(codecs.IncrementalEncoder):
def encode(self, input, final=False):
return codecs.charmap_encode(input,self.errors,_cp437_encoding_map)[0]
class _Cp437IncrementalDecoder(codecs.IncrementalDecoder):
def decode(self, input, final=False):
return codecs.charmap_decode(input,self.errors,_cp437_decoding_map)[0]
class _Cp437StreamWriter(_Cp437Codec,codecs.StreamWriter):
pass
class _Cp437StreamReader(_Cp437Codec,codecs.StreamReader):
pass
_Cp437CodecInfo = codecs.CodecInfo(
# https://github.com/python/cpython/blob/v3.12.1/Lib/encodings/cp437.py#L34
name='x-microsoft-437',
encode=_Cp437Codec().encode,
decode=_Cp437Codec().decode,
incrementalencoder=_Cp437IncrementalEncoder,
incrementaldecoder=_Cp437IncrementalDecoder,
streamreader=_Cp437StreamReader,
streamwriter=_Cp437StreamWriter,
)
_cp437_encoding_map = _psf_cp437.encoding_map | {
0x263a: 0x01,
0x263b: 0x02,
0x2665: 0x03,
0x2666: 0x04,
0x2663: 0x05,
0x2660: 0x06,
0x2642: 0x0b,
0x2640: 0x0c,
0x266b: 0x0e,
0x263c: 0x0f,
0x25ba: 0x10,
0x25c4: 0x11,
0x2195: 0x12,
0x203c: 0x13,
0x00b6: 0x14,
0x00a7: 0x15,
0x25ac: 0x16,
0x21a8: 0x17,
0x2191: 0x18,
0x2193: 0x19,
0x2192: 0x1a,
0x2190: 0x1b,
0x221f: 0x1c,
0x2194: 0x1d,
0x25b2: 0x1e,
0x25bc: 0x1f,
0x2302: 0x7f,
}
_cp437_decoding_map = _psf_cp437.decoding_map | {
0x01: 0x263a,
0x02: 0x263b,
0x03: 0x2665,
0x04: 0x2666,
0x05: 0x2663,
0x06: 0x2660,
0x0b: 0x2642,
0x0c: 0x2640,
0x0e: 0x266b,
0x0f: 0x263c,
0x10: 0x25ba,
0x11: 0x25c4,
0x12: 0x2195,
0x13: 0x203c,
0x14: 0x00b6,
0x15: 0x00a7,
0x16: 0x25ac,
0x17: 0x21a8,
0x18: 0x2191,
0x19: 0x2193,
0x1a: 0x2192,
0x1b: 0x2190,
0x1c: 0x221f,
0x1d: 0x2194,
0x1e: 0x25b2,
0x1f: 0x25bc,
0x7f: 0x2302
}