fileinput不是“神器”,而是在顺序读取多文件且不关心内存时更省心安全的工具;它按需开闭文件避免句柄耗尽,需在循环内调用filename()和isfirstline(),编码错误须显式指定openhook,inplace模式有重命名风险。

fileinput 不是“神器”,它只是在特定场景下比手动 open() 更省心、更安全——尤其是当你需要**顺序读取一堆文件、不关心内存占用、又不想自己管文件开关和异常恢复**的时候。
它解决的不是“能不能做”,而是“少写错、少漏关、少爆内存”。
为什么 fileinput.input() 不会爆文件句柄?
操作系统对同时打开的文件数有限制(常见默认 1024)。手动用 for f in files: with open(f) as fp: 嵌套太深或忘了 with,就容易触发 OSError: [Errno 24] Too many open files。fileinput.input() 内部严格按需打开、读完一行立刻缓冲、换文件时自动关闭前一个句柄——你传一百个文件,同一时刻最多只打开 1 个。
- 它不缓存全部内容,只维护当前文件的
fp和读取位置 - 遇到空文件会立即
close(),不占资源 - 即使某个文件中途
OSError,已打开的其他文件仍会被正常清理(尤其在with块中)
fileinput.filename() 和 fileinput.isfirstline() 怎么配合用才不踩坑?
这两个函数必须在 for line in fileinput.input(...) 循环体内调用,且顺序敏感:只有读到新文件第一行时,fileinput.isfirstline() 才返回 True,此时 fileinput.filename() 已更新为新文件名。
- 不能在循环外调用
fileinput.filename(),否则返回None - 不能靠
fileinput.lineno() == 1判断首行——它是全局累计行号,不是当前文件内行号 - 想在每份文件开头插入分隔符,得写成:
if fileinput.isfirstline(): print(f'=== {fileinput.filename()} ===')
编码错误频发?openhook 参数不是摆设
fileinput.input() 默认用系统编码(如 Windows 上是 cp936),遇到 UTF-8 文件无 BOM 就直接抛 UnicodeDecodeError。这不是 bug,是设计如此——它不做猜测,要你显式声明。
- 必须传
openhook=fileinput.hook_encoded('utf-8'),而不是只写encoding='utf-8'(后者在旧版本 Python 中无效) -
hook_compressed()仅支持.gz/.bz2,不支持.zip或.xz;自定义openhook函数必须接收filename和mode两个参数,并返回类文件对象 - 路径不存在或权限不足时,
fileinput照样报OSError,它不帮你跳过——校验路径得前置做
别误用 inplace=True 模式
这个参数开启后,fileinput 会把 print() 输出重定向到当前输入文件,实现“边读边写”。但它本质是先 mv 原文件 + 创建同名新文件 + 写入 + 关闭,所以:
立即学习“Python免费学习笔记(深入)”;
- 原文件被 rename,硬链接失效,符号链接指向丢失
- 如果中途崩溃,可能只剩备份文件(带
backup后缀),原文件已消失 - 不能用于标准输入(
sys.stdin)或管道流,会报RuntimeError - 多文件时,每个文件独立处理,但
fileinput.filename()在inplace模式下仍可用


















