print(..., flush=True) 拖慢性能因强制每次刷新缓冲区,触发额外系统调用;高频场景应优先用 sys.stdout.reconfigure(line_buffering=True),或底层 sys.stdout.buffer.write() 手动控制刷新。

为什么 print(..., flush=True) 会拖慢性能
因为每次调用都会强制刷新缓冲区,绕过系统默认的行缓冲或全缓冲策略,触发一次 sys.stdout.flush() + 底层 write() 系统调用。在高频打印(比如日志循环、进度条)中,这会让 I/O 次数从「合并写入」退化为「逐条写入」,实测可能慢 5–10 倍。
用 sys.stdout.reconfigure() 一次性设为无缓冲更合理
Python 3.7+ 支持运行时重配 stdout 缓冲模式,比反复加 flush=True 更轻量。它只在启动时生效一次,后续所有 print() 自动实时输出,不额外开销。
实操建议:
- 在程序开头尽早调用:
import sys sys.stdout.reconfigure(line_buffering=True)
(注意:不是buffering=0,那是无缓冲,对终端不友好;line_buffering=True才是行刷新,兼顾可读性与实时性) - 避免在多线程里调用 ——
reconfigure()不是线程安全的 - Windows 控制台下可能表现略有差异,建议搭配
colorama.init()或os.system('')触发虚拟终端支持
高频场景下,直接写 sys.stdout.buffer.write() 绕过 print
当你要每毫秒打一条状态(比如监控脚本),连 print() 的格式化开销都成了瓶颈,这时该换底层接口。
关键点:
- 必须手动换行并编码:
sys.stdout.buffer.write(b'alive\n'),否则不显示 - 仍需
sys.stdout.buffer.flush()—— 但可以控制频率,比如每 10 条刷一次,而非每条都刷 - 丢失了
sep/end等便利,适合纯 ASCII 状态输出,不适合调试式带变量的打印
别忽略环境差异:容器、重定向、IDE 终端行为不一致
flush=True 在本地终端有效,但一旦管道重定向到文件(python script.py > out.log)或进 Docker,Python 会自动切到全缓冲,此时 flush=True 才真正必要;而 PyCharm / VS Code 的内置终端可能模拟行缓冲,导致你以为没生效。
验证当前缓冲模式的方法:
import sys print(sys.stdout.line_buffering) # True / False print(sys.stdout.buffering) # -1 (default), 0 (unbuffered), N (bytes)
复杂点在于:没有银弹。行缓冲适合交互终端,无缓冲适合管道,而高频写入还得自己攒 buffer —— 关键是先看清楚你到底在往哪儿输出,再选路。











