在Python中显示unicode字符串的宽度

时间:2014-03-06 13:05:14

标签: 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.
    zoothèque          | zooth.
    zooveterinar-       | zoovet.
    zoovetinstitut-     | zoovetinst.
    母                   | 母母

>>> s = 'è'
>>> len(s)
    2
>>> [ord(c) for c in s]
    [101, 768]
>>> unicodedata.name(s[1])
    'COMBINING GRAVE ACCENT'
>>> s2 = '母'
>>> len(s2)
    1

可以看出,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

1 个答案:

答案 0 :(得分:2)

您有几种选择:

  1. 某些控制台支持转义序列,用于像素精确定位光标。不过可能会导致一些叠印。

    历史记录:这种方法在Amiga终端中用于在控制台窗口中显示图像,方法是打印一行文本,然后将光标向下推进一个像素。文本行的剩余像素慢慢构建了一个图像。

  2. 在代码中创建一个表,其中包含控制台/终端窗口中使用的字体中所有Unicode字符的实际(像素)宽度。使用UI框架和一个小的Python脚本来生成此表。

    然后添加使用此表计算文本实际宽度的代码。但结果可能不是控制台中字符宽度的倍数。与像素精确的光标移动一起,这可以解决您的问题。

    注意:您必须为连字(fi,fl)和composites添加特殊处理。或者,您可以在不打开窗口的情况下加载UI框架,并使用图形基元来计算字符串宽度。

  3. 使用制表符(\t)缩进。但是,只有在shell实际使用实际文本宽度放置光标时,这才有用。许多终端只会计算字符数。

  4. 使用表创建一个HTML文件,并在浏览器中查看。