Python中f-string格式化输出列宽不一致,异常排查求助
问题根源:Unicode字符显示宽度与码点数量不匹配
你的代码用len()计算列名长度,但len()统计的是字符串的Unicode码点数量,而非终端中的实际显示宽度。当CSV列名包含组合字符(比如由基础字符e加组合重音符构成的é,对应两个Unicode码点)时,这类字符的码点数量是2,但终端显示仅占1个字符宽度,导致你计算的longest_key(最大列名码点长度+5)比实际需要的显示宽度偏大。
对于无组合字符的列名,len(k)等于实际显示宽度,格式化时会填充足够空格;而含组合字符的列名,实际显示宽度小于len(k),填充的空格数变少,视觉上就出现了列宽偏移。
解决方案:使用实际显示宽度计算列宽
用wcwidth库计算字符串在终端中的实际显示宽度,替代len():
- 安装依赖库:
pip install wcwidth
- 修改后的代码:
import os import csv from wcwidth import wcswidth def print_longest(source): csv_raw = None if os.path.isfile(source): csv_raw = csv.DictReader(open(source, encoding='utf-8')) longest_key = 0 longests = {} for row in csv_raw: for k, v in row.items(): # 计算列名的实际显示宽度 klen = wcswidth(k) if klen > longest_key: longest_key = klen # 计算值的实际显示宽度(若需要对齐值可保留) vlen = wcswidth(v) if k not in longests: longests[k] = vlen elif vlen > longests[k]: longests[k] = vlen longest_key += 5 t1 = "Column" t2 = "Length" print(f"{t1:{longest_key}} | {t2}") for k, v in longests.items(): print(f"{k:{longest_key}} | {v}")
验证方法
添加以下代码,查看列名的码点数量与实际显示宽度差异:
for k in longests.keys(): print(f"列名: {repr(k)}, 码点数量: {len(k)}, 显示宽度: {wcswidth(k)}")
如果某行的码点数量大于显示宽度,说明该行列名包含了组合字符或其他显示宽度与码点数量不一致的字符,这就是偏移的直接原因。
内容的提问来源于stack exchange,提问作者Fabrice Quenneville
相关产品推荐
相关产品推荐

