textwrap.fill() 默认不自适应终端是因为它是纯文本模块,与终端无关,必须显式传入 width(默认70);需用 shutil.get_terminal_size().columns 动态获取并 fallback 到最小宽度20。

直接用 textwrap.fill() 就能按终端宽度自动换行,但默认不感知真实终端宽度,得手动传 width 或用 shutil.get_terminal_size() 动态获取。
为什么 textwrap.fill() 默认不自适应终端?
textwrap 是纯文本处理模块,和终端无关。它没有内置“读取当前终端宽度”的能力,所有换行都依赖显式传入的 width 参数(默认 70)。如果你直接调用 textwrap.fill(text),它就按 70 列切分,哪怕你的终端是 120 列或 40 列。
- 真实终端宽度需靠
shutil.get_terminal_size().columns获取,且该值可能为 0(如重定向到文件或 CI 环境) -
textwrap.TextWrapper实例的width属性可动态赋值,适合复用 - 别依赖
os.environ.get('COLUMNS')—— 它不可靠,shell 可能没导出或已过期
如何安全获取并使用终端宽度?
先查终端尺寸,再 fallback 到合理默认值(比如 80),避免 width ≤ 0 导致异常或无限循环。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
import shutil import textwrap <p>def wrap_to_terminal(text): width = shutil.get_terminal_size().columns</p><h1>保留左右各 1 字符边距,且最小不小于 20</h1><pre class="brush:php;toolbar:false;">width = max(20, width - 2) return textwrap.fill(text, width=width)
示例
long_text = "Python's textwrap module provides tools for wrapping and formatting text. It's especially useful for CLI output." print(wrap_to_terminal(long_text))
- 减去 2 是为避免某些终端在行尾显示滚动条或截断时出问题
-
max(20, ...)防止终端报告 0 或 1 列(常见于管道、cron、GitHub Actions) - 若需保留缩进(如段落首行缩进),用
initial_indent和subsequent_indent参数
textwrap.dedent() 和 textwrap.indent() 的典型误用场景
很多人在格式化多行字符串前忘记去缩进,导致每行前面多出空格,再 wrap 就错位;或者想加统一前缀却误用了 replace('\n', '\n> ') 这种脆弱方式。
-
textwrap.dedent()只处理字符串字面量里的公共前导空白,对运行时拼接的字符串无效 -
textwrap.indent(text, '> ')会正确处理每行(包括空行),比正则或splitlines()手动处理更健壮 - 组合使用示例:
textwrap.fill(textwrap.dedent(long_str), width=...),先清理再换行
真正容易被忽略的是:当文本含全角字符(中文、日文)、ANSI 转义序列(颜色码)或制表符时,textwrap 按“字符数”计宽,不是“显示宽度”。这时候 width 值需要额外校准,或者改用 rich.text / ansiwrap 这类支持双宽字符的库。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










