Chr*_*ger 7 python string unicode width python-unicode
如何确定Python 3.x中Unicode字符串的显示宽度,以及是否有一种方法可以使用该信息将这些字符串与对齐str.format()
?
激励示例:将字符串表打印到控制台。一些字符串包含非ASCII字符。
>>> for title in d.keys():
>>> print("{:<20} | {}".format(title, d[title]))
zootehni- | zooteh.
zootekni- | zootek.
zoothe?que | zooth.
zooveterinar- | zoovet.
zoovetinstitut- | zoovetinst.
? | ??
>>> s = 'e?'
>>> len(s)
2
>>> [ord(c) for c in s]
[101, 768]
>>> unicodedata.name(s[1])
'COMBINING GRAVE ACCENT'
>>> s2 = '?'
>>> len(s2)
1
Run Code Online (Sandbox Code Playgroud)
可以看出,str.format()
仅将字符串(len(s)
)中代码点的数量作为宽度,导致输出中的列偏斜。搜索该unicodedata
模块,没有发现任何建议的解决方案。
Unicode规范化可以解决è的问题,但不能解决亚洲字符(通常显示宽度更大)的问题。类似地,存在零宽度的unicode字符(例如,零宽度的空间用于允许单词内的换行符)。您无法使用规范化解决这些问题,因此请不要建议“规范化字符串”。
编辑:添加了有关规范化的信息。
编辑2:在我的原始数据集中,也有一些欧洲组合字符,即使标准化后也不会导致单个代码点:
zwemwater | zwemw.
zwia?z- | zw.
>>> s3 = 'a\u0322' # The 'a + combining retroflex hook below' from zwiaz
>>> len(unicodedata.normalize('NFC', s3))
2
Run Code Online (Sandbox Code Playgroud)
您有多种选择:
某些控制台支持转义序列以实现光标的像素精确定位。不过,可能会导致一些叠印。
历史记录:这种方法用于 Amiga 终端,通过打印一行文本,然后将光标向下移动一个像素,在控制台窗口中显示图像。文本行的剩余像素慢慢地构建了图像。
在代码中创建一个表,其中包含控制台/终端窗口中使用的字体中的所有 Unicode 字符的实际(像素)宽度。使用 UI 框架和一个小型 Python 脚本来生成此表。
然后添加使用此表计算文本实际宽度的代码。不过,结果可能不是控制台中字符宽度的倍数。与像素精确的光标移动一起,这可能会解决您的问题。
注意:您必须为连字 (fi, fl) 和合成词添加特殊处理。或者,您可以在不打开窗口的情况下加载 UI 框架,并使用图形基元来计算字符串宽度。
使用制表符 ( \t
) 进行缩进。但只有当您的 shell 实际上使用真实文本宽度来放置光标时,这才会有帮助。许多终端只会简单地计算字符数。
创建一个包含表格的 HTML 文件并在浏览器中查看它。