Python Unicode - Windows 控制台可以打印哪些字符?
Python Unicode - What Characters Can Be Printed in Windows Console?
哪些 Unicode 字符可以在 Python 的 Windows 控制台中打印?
以下代码
for code in range(1114112):
print(chr(code), end=",")
给出了令人印象深刻的结果,包括一个错误:
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 0: surrogates not allowed
然而,str
的文档声称值高达 0x110000
是允许的。
有没有办法让更多的字符显示出来?
为了回答你的问题,我们需要检查几层 Unicode。
有效的 Unicode 代码点是从 0 到 U+10FFFF。您可以使用 unicodedata.category(char)
查找具有 Unicode 代码点的类别。
从 U+D800 到 U+DFFF 的值是代理项,不应使用它们(在 UTF-16 中它们不能是 encoded/decoded)。 [它们用于增强 UCS-2(如此旧的 Unicode,直到 U+FFFF 都有代码点)到 UTF-16(到 U+10FFFF)。旧 programs/languages(如 Javascript)可能使用两个代理表示,而不是一个 UTF-16 代码点。
注意:Python允许使用它们是因为surrogateescape(主要用于阅读sys.argv),但您应该忽略它们,但仅在内部使用它们, 在正确转换它们之前。
因此,请勿尝试使用此类代码。
还有 非字符:U+FDD0–U+FDEF 和 FFFE 或 FFFF(即 U+FFFE、U+FFFF、U+1FFFE、U+ 1FFFF, … U+10FFFE, U+10FFFF) [from Wikipedia, Unicode], which should not be used, but ev. BOM (U+FEFF), but in this case only as first character. Reason: the first block: What's the purpose of the noncharacters U+FDD0 to U+FDEF?, others: 自动检测编码,所以我们不应该有 confusing 代码点:如果你检测到它们,您知道自己使用了错误的编码,并且更改了编码,直到获得有效的第一个代码点。
现在,使用 unicodedata.category(char)
,您还可以获得代码的类别(请参阅 Unicode character categories)。 U+1F、U+7F–U+9F之前的字符为控制字符,不打印。
您可能有格式化字符,可以修改附近的字符。
因此您可能希望排除 C*
(注意:这将丢弃所有上述字符),也可能排除 Z*
(空格)字符类别。
所以你有可打印的字符,由 unicodedata
标准模块知道。使用 unicodedata.unidata_version
检查数据库更新的 unicode 版本。你可能会。允许 Cn
类别(未分配):也许现在它们已分配。
但这还不够。您需要一种字体来显示这些字符。 Google 有 "No Tofu fonts" 这是(我认为)最完整的字体。
但这还不够。您只会得到字符的标准表示(可能不会,您应该在每个字符后添加一个 U+200C (ZWNJ),以强制字体不连接字符(例如在印度语中)。但是您会错过所有字符由代码点的组合表示:例如,许多重音字符、用圆圈或正方形括起来的字符、国家标志(您需要按正确顺序排列两个国家代码字符)等
注意:我很好奇如何从字体文件中获取所有字形,但这不是你的问题。
附录:
忘了说:组合字符不能单独显示,所以需要在e.g.使用 U+25CC,您可以使用 unicodedata.combining(chr)
.
检查它们
所以你可以使用这个代码
# if your console is not UTF-8 (or any unicode encoding) and python
# do no get it, you will get garbage
import unicodedata
combining = '\u25cc'
placeholder = '\ufffd'
zwnj = '\u200c'
line = ''
for code in range(0x10FFFF+1):
c = chr(code)
cat = unicodedata.category(c)
if cat.startswith('C'): # and cat != 'Cn':
r = placeholder
elif cat.startswith('Z'):
r = ' '
elif unicodedata.combining(c) > 0:
r = combining + c + zwnj
else:
r = c + zwnj
line += r
if code % 256 == 255:
print(line)
line = ''
哪些 Unicode 字符可以在 Python 的 Windows 控制台中打印?
以下代码
for code in range(1114112):
print(chr(code), end=",")
给出了令人印象深刻的结果,包括一个错误:
UnicodeEncodeError: 'utf-8' codec can't encode character '\ud800' in position 0: surrogates not allowed
然而,str
的文档声称值高达 0x110000
是允许的。
有没有办法让更多的字符显示出来?
为了回答你的问题,我们需要检查几层 Unicode。
有效的 Unicode 代码点是从 0 到 U+10FFFF。您可以使用 unicodedata.category(char)
查找具有 Unicode 代码点的类别。
从 U+D800 到 U+DFFF 的值是代理项,不应使用它们(在 UTF-16 中它们不能是 encoded/decoded)。 [它们用于增强 UCS-2(如此旧的 Unicode,直到 U+FFFF 都有代码点)到 UTF-16(到 U+10FFFF)。旧 programs/languages(如 Javascript)可能使用两个代理表示,而不是一个 UTF-16 代码点。
注意:Python允许使用它们是因为surrogateescape(主要用于阅读sys.argv),但您应该忽略它们,但仅在内部使用它们, 在正确转换它们之前。
因此,请勿尝试使用此类代码。
还有 非字符:U+FDD0–U+FDEF 和 FFFE 或 FFFF(即 U+FFFE、U+FFFF、U+1FFFE、U+ 1FFFF, … U+10FFFE, U+10FFFF) [from Wikipedia, Unicode], which should not be used, but ev. BOM (U+FEFF), but in this case only as first character. Reason: the first block: What's the purpose of the noncharacters U+FDD0 to U+FDEF?, others: 自动检测编码,所以我们不应该有 confusing 代码点:如果你检测到它们,您知道自己使用了错误的编码,并且更改了编码,直到获得有效的第一个代码点。
现在,使用 unicodedata.category(char)
,您还可以获得代码的类别(请参阅 Unicode character categories)。 U+1F、U+7F–U+9F之前的字符为控制字符,不打印。
您可能有格式化字符,可以修改附近的字符。
因此您可能希望排除 C*
(注意:这将丢弃所有上述字符),也可能排除 Z*
(空格)字符类别。
所以你有可打印的字符,由 unicodedata
标准模块知道。使用 unicodedata.unidata_version
检查数据库更新的 unicode 版本。你可能会。允许 Cn
类别(未分配):也许现在它们已分配。
但这还不够。您需要一种字体来显示这些字符。 Google 有 "No Tofu fonts" 这是(我认为)最完整的字体。
但这还不够。您只会得到字符的标准表示(可能不会,您应该在每个字符后添加一个 U+200C (ZWNJ),以强制字体不连接字符(例如在印度语中)。但是您会错过所有字符由代码点的组合表示:例如,许多重音字符、用圆圈或正方形括起来的字符、国家标志(您需要按正确顺序排列两个国家代码字符)等
注意:我很好奇如何从字体文件中获取所有字形,但这不是你的问题。
附录:
忘了说:组合字符不能单独显示,所以需要在e.g.使用 U+25CC,您可以使用 unicodedata.combining(chr)
.
所以你可以使用这个代码
# if your console is not UTF-8 (or any unicode encoding) and python
# do no get it, you will get garbage
import unicodedata
combining = '\u25cc'
placeholder = '\ufffd'
zwnj = '\u200c'
line = ''
for code in range(0x10FFFF+1):
c = chr(code)
cat = unicodedata.category(c)
if cat.startswith('C'): # and cat != 'Cn':
r = placeholder
elif cat.startswith('Z'):
r = ' '
elif unicodedata.combining(c) > 0:
r = combining + c + zwnj
else:
r = c + zwnj
line += r
if code % 256 == 255:
print(line)
line = ''