本文要点
width 参数给的是每行允许的最大字符数,默认 70
缩进和折行是两件事,textwrap 把它们分开处理
wrap 和 fill 处理的是折行,indent 和 dedent 处理的是整段文本的缩进,两者用途不同

本文目录
先分清 wrap 返回列表、fill 返回整段字符串
如果你要把一段长文本塞进终端宽度里,先决定你要的是“一行一行的列表”还是“拼好的一整段”。
textwrap.wrap(text, width=70) 返回一个字符串列表,每个元素是一行,不含换行符;textwrap.fill(text, width=70) 返回一个字符串,行与行之间用换行符连起来。按官方文档,fill() 就是 "\n".join(wrap(text, ...)) 的简写,两者接受完全相同的关键字参数。
所以选法很简单:后面还要逐行处理(比如加行号、按行判断长度),用 wrap;只想直接打印或写进一个变量,用 fill。
本文只处理内存里的英文或简单样例字符串,不读写文件,也不保证按中文显示宽度计量。下面所有文本都是自建练习示例。
width 是每行上限,长单词默认会被切断
width 参数给的是每行允许的最大字符数,默认 70。textwrap 会尽量在空格处断行,把单词整体挪到下一行,而不是从单词中间切开。
自建示例:
import textwrap
text = "Wrapping text in a terminal is a common task for small tools."
print(textwrap.fill(text, width=30))输出是每行不超过 30 个字符、在空格处断开的几行。注意两点:
1. 每行长度通常小于 width,因为断点落在空格上,剩下的空间放不下下一个单词。
2. 如果某个单词本身就比 width 长,默认参数 break_long_words=True 会把它切断,以保证没有一行超过 width。文档写的是:只有 break_long_words 设为 false 时,长单词才不被切断,此时该单词单独占一行,这一行可能超出 width。
所以排查“为什么这行特别长”时,先看是不是把 break_long_words 设成了 false,而不是默认行为。
width 只按字符计数,不按显示宽度。中文、全角字符、emoji 在终端里占的列数可能和字符数不一致,本文不保证这类样例的折行结果。
indent 和 subsequent_indent 只管缩进,且计入行宽
缩进和折行是两件事,textwrap 把它们分开处理。
- initial_indent:加在第一行前面的字符串,默认空。文档说明它计入第一行的长度。
- subsequent_indent:加在除第一行之外每一行前面的字符串,默认空。文档说明它计入除第一行外每一行的长度。
自建示例:
import textwrap
text = "Wrapping text in a terminal is a common task for small tools."
print(textwrap.fill(text, width=40, initial_indent="> ", subsequent_indent=" "))第一行以 "> " 开头,后续行以两个空格开头。关键点:缩进字符串的长度会占用 width 的额度。也就是说,subsequent_indent 越长,留给正文的字符数越少。
这一点决定了缩进要交给 initial_indent 和 subsequent_indent 参数,让 textwrap 在计算断点时就把它们算进去,而不是折行之后再自己往行首拼字符串。
indent 与 dedent:给整段加缩进、去掉公共缩进
wrap 和 fill 处理的是折行,indent 和 dedent 处理的是整段文本的缩进,两者用途不同。
textwrap.indent(text, prefix) 给 text 的每一行加 prefix。文档说明:默认只给不是纯空白的行加前缀(包括行尾换行符在内的整行都算),predicate 参数可以改这个规则。
textwrap.dedent(text) 去掉每一行开头的公共空白。它找的是所有行共有的那段缩进,把它删掉。
自建示例:
import textwrap
block = """
first line
second line
"""
print(repr(textwrap.dedent(block)))去公共缩进后,两行开头的四个空格被删掉。dedent 只删公共部分:如果某行缩进比别人少,它就以最少的那行为准,其余行保留多出来的空格。
一个容易踩的坑:文档明确说,制表符和空格都被当作空白,但两者不相等。所以 " hello" 和 "\thello" 这两行被认为没有公共前导空白,dedent 不会删掉它们前面的空白。排查时先看是不是把 tab 和空格混着用了。
检查结果:打印每行长度和 repr
折行结果对不对,靠肉眼看容易漏掉行尾空格和缩进。建议打印每行长度和 repr。
自建示例:
import textwrap
text = "Wrapping text in a terminal is a common task for small tools."
for w in (40, 20):
print("width =", w)
lines = textwrap.wrap(text, width=w, subsequent_indent=" ")
for line in lines:
print(len(line), repr(line))
print()检查三件事:
1. 每行 len 是否都不超过 width。超了,先确认 break_long_words 是不是被设成了 false,再确认缩进有没有算进 width。
2. 后续行是否都带上了 subsequent_indent。
3. repr 里有没有多余的行尾空格。
如果结果和预期不符,先确认你用的是 wrap 还是 fill,再确认缩进是交给参数还是事后拼接。
使用限制:只处理内存文本,不保证中文宽度
本文的范围只有一条:处理内存里的英文或简单样例字符串。
几个明确限制:
1. textwrap 按字符数计算,不按终端显示列数。中文、全角标点、emoji 的显示宽度和字符数不一致,本文不保证这类文本的折行结果,也不声称与浏览器排版一致。
2. 它不读写文件。要处理文件内容,先自己读进来,处理完再自己写出去。
3. 它不处理制表符对齐,也不管终端实际宽度。终端宽度要自己取,再传给 width。
4. 本文不展开 shorten、max_lines、placeholder 等截断相关参数,也不展开 break_on_hyphens 的细节。
参考资料:Python 官方 textwrap 文档(https://docs.python.org/3/library/textwrap.html)。上面所有示例均为自建练习,不是对真实终端或真实文件的记录。
观看知识要点视频 18 秒
18秒无旁白要点导览,文字来自已审核正文;完整步骤、条件及参考资料见下方。
参考资料
以下原始资料提供本文依据;请结合日期、适用条件和产品说明查阅。
请结合原始资料的适用条件阅读。
返回效率工具 →