search
HomeBackend DevelopmentPython TutorialPython计算字符宽度的方法

本文实例讲述了Python计算字符宽度的方法。分享给大家供大家参考,具体如下:

最近在用python写一个CLI小程序,其中涉及到计算字符宽度,目标是以友好的方式将一个长字符串截取为等宽的片段。

对于unicode字符,python的len函数可以准确的计算其中所包含的字符个数,但是个数并不代表宽度,如:

>>>len(u'你好a')
3

因此无法简单的使用这种方式来计算宽度。

GBK decode

首先我想到GBK编码,00–7F范围内的字符是一字节编码,其余是双字节编码,正好与字符的宽度大体一致,于是有了这样的投机取巧的办法(假设取8个宽度):

>>> a = u'hello你好'
>>> b=a.encode('gbk')
>>> try:
...  print b[:8].decode('gbk')
... except:
...  print b[:7].decode('gbk')
...
hello你

如代码所示,首先将unicode的字符串进行GBK编码,然后截取8个字节的宽度后尝试用GBK解码,若解码失败,则少截取一个宽度,截取7个字节后使用GBK解码。

虽然初步解决了问题,但是这样做的硬伤很明显。首先代码不优雅,以试错的方式运行;其次GBK所能表示的字符有限,对于大量GBK编码以外的字符无法支持。

East_Asian_Width

徘徊很久之后,偶然发现 Unicode Character Database 标准中有East_Asian_Width 属性,并有以下可能值:

# East_Asian_Width (ea)
ea ; A     ; Ambiguous  不确定
ea ; F     ; Fullwidth  全宽
ea ; H     ; Halfwidth  半宽
ea ; N     ; Neutral   中性
ea ; Na    ; Narrow    窄
ea ; W     ; Wide     宽

其中除A不确定外,F/H/N/Na/W都能很明确的知道宽度,如果保守起见,将A视为宽度为2的话,则很容易给出单个字符的宽度:

>>> import unicodedata
>>> def chr_width(c):
...  if (unicodedata.east_asian_width(c) in ('F','W','A')):
...   return 2
...  else:
...   return 1
>>> chr_width(u'你')
2
>>> chr_width(u'a')
1

到现在似乎已经可以满足要求了,但是实际使用中发现属性为A的字符真不少见,最典型的就是中文的双引号:

>>> chr_width(u'”')
2

在大多数等宽字体中,中文双引号都是只占一位宽的,如果一行里有多个中文双引号,则累加的误判宽度将会使截取效果大打折扣,无疑这也不是最好的办法。

urwid的解决方案

urwid  是一个成熟的python终端UI库,它在curses的基础之上包装了类似HTML的控件用以显示文本内容,如果有这方面的开发需求,非常推荐此库,比直接使用curses库方便很多,非常棒的是它对unicode的文本宽度截取非常准确,让我大为惊讶,于是翻开它的源码一探究竟,文本宽度计算方面其核心代码如下:

widths = [
  (126,  1), (159,  0), (687,   1), (710,  0), (711,  1),
  (727,  0), (733,  1), (879,   0), (1154, 1), (1161, 0),
  (4347,  1), (4447,  2), (7467,  1), (7521, 0), (8369, 1),
  (8426,  0), (9000,  1), (9002,  2), (11021, 1), (12350, 2),
  (12351, 1), (12438, 2), (12442,  0), (19893, 2), (19967, 1),
  (55203, 2), (63743, 1), (64106,  2), (65039, 1), (65059, 0),
  (65131, 2), (65279, 1), (65376,  2), (65500, 1), (65510, 2),
  (120831, 1), (262141, 2), (1114109, 1),
]
def get_width( o ):
  """Return the screen column width for unicode ordinal o."""
  global widths
  if o == 0xe or o == 0xf:
    return 0
  for num, wid in widths:
    if o <= num:
      return wid
  return 1

如代码所示,首先根据unicode的官方EastAsianWidth  文档整理出字符宽度的范围表,然后使用unicode代码查表。使用之前的例子测试:

>>> get_width(ord(u'a'))
1
>>> get_width(ord(u'你'))
2
>>> get_width(ord(u'”'))
1

完全准确,而且在实际应用中的表现也比较好,是一个理想的解决方案,更多技巧请查阅urwid的old_str_util.py 源码。

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python图片操作技巧总结》、《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
详细讲解Python之Seaborn(数据可视化)详细讲解Python之Seaborn(数据可视化)Apr 21, 2022 pm 06:08 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于Seaborn的相关问题,包括了数据可视化处理的散点图、折线图、条形图等等内容,下面一起来看一下,希望对大家有帮助。

详细了解Python进程池与进程锁详细了解Python进程池与进程锁May 10, 2022 pm 06:11 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于进程池与进程锁的相关问题,包括进程池的创建模块,进程池函数等等内容,下面一起来看一下,希望对大家有帮助。

Python自动化实践之筛选简历Python自动化实践之筛选简历Jun 07, 2022 pm 06:59 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于简历筛选的相关问题,包括了定义 ReadDoc 类用以读取 word 文件以及定义 search_word 函数用以筛选的相关内容,下面一起来看一下,希望对大家有帮助。

归纳总结Python标准库归纳总结Python标准库May 03, 2022 am 09:00 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于标准库总结的相关问题,下面一起来看一下,希望对大家有帮助。

Python数据类型详解之字符串、数字Python数据类型详解之字符串、数字Apr 27, 2022 pm 07:27 PM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于数据类型之字符串、数字的相关问题,下面一起来看一下,希望对大家有帮助。

分享10款高效的VSCode插件,总有一款能够惊艳到你!!分享10款高效的VSCode插件,总有一款能够惊艳到你!!Mar 09, 2021 am 10:15 AM

VS Code的确是一款非常热门、有强大用户基础的一款开发工具。本文给大家介绍一下10款高效、好用的插件,能够让原本单薄的VS Code如虎添翼,开发效率顿时提升到一个新的阶段。

详细介绍python的numpy模块详细介绍python的numpy模块May 19, 2022 am 11:43 AM

本篇文章给大家带来了关于Python的相关知识,其中主要介绍了关于numpy模块的相关问题,Numpy是Numerical Python extensions的缩写,字面意思是Python数值计算扩展,下面一起来看一下,希望对大家有帮助。

python中文是什么意思python中文是什么意思Jun 24, 2019 pm 02:22 PM

pythn的中文意思是巨蟒、蟒蛇。1989年圣诞节期间,Guido van Rossum在家闲的没事干,为了跟朋友庆祝圣诞节,决定发明一种全新的脚本语言。他很喜欢一个肥皂剧叫Monty Python,所以便把这门语言叫做python。

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
2 weeks agoBy尊渡假赌尊渡假赌尊渡假赌

Hot Tools

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

EditPlus Chinese cracked version

EditPlus Chinese cracked version

Small size, syntax highlighting, does not support code prompt function

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),