fileinput.input() 不能直接写入文件,因为它默认只读,即使启用 inplace=true 也仅重定向 stdout 到临时文件并原子替换,需通过 print() 输出才能生效。

fileinput.input() 为什么不能直接写入文件
因为 fileinput.input() 默认以只读模式打开文件,即使传入 inplace=True,它也只是把 stdout 重定向到临时文件并做原子替换——你不能在循环中调用 f.write() 或手动写入。常见错误是误以为拿到的是可写文件对象,结果报 io.UnsupportedOperation: not writable。
正确做法是:依赖 fileinput 自动接管输出,所有 print() 都会落到目标位置。
- 必须启用
inplace=True,否则print()输出到终端,原文件不变 - 使用
sys.stdout是无效的;fileinput会临时替换sys.stdout,但仅限于print()调用 - 若需保留原始文件备份,加参数
backup='.bak'(如backup='.orig')
如何安全地逐行查找并替换(含正则)
直接对 line 做字符串 .replace() 最简单,但无法处理复杂模式;用 re.sub() 更灵活,注意要确保 re 已导入,且替换后仍需 print() 输出。
示例:把所有 old_func 替换为 new_func,仅匹配单词边界:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
import fileinput
import re
<p>for line in fileinput.input('script.py', inplace=True, backup='.bak'):
line = re.sub(r'\bold_func\b', 'new_func', line)
print(line, end='') # 注意 end='',否则每行多一个空行
</p>
-
end=''很关键:因为line已含换行符,不设end=''会导致双换行 - 若用
.replace(),写法更直白:line = line.replace('foo', 'bar') - 正则替换时,避免用
re.compile()在循环内重复编译;应提前编译好再进循环
多文件批量处理时怎么控制范围
fileinput.input() 接收文件路径列表或 glob 模式(需配合 glob 模块),但要注意:它不会自动跳过二进制文件,遇到编码异常会中断。实际中建议先过滤掉非文本文件。
- 支持通配符:
fileinput.input(['*.py', 'config/*.yaml'], inplace=True) - 但
fileinput不解析 shell 通配,所以'*.py'必须由 Python 展开,推荐用glob.glob('*.py')预处理 - 用
fileinput.filename()获取当前处理的文件名,可用于条件跳过:if fileinput.filename().endswith('_test.py'): continue - 遇到
UnicodeDecodeError,可在循环外加encoding='utf-8'参数(Python 3.10+ 支持)
为什么改完文件内容却没变?常见静默失败点
最常被忽略的是:没调用 print()。只要进了 inplace=True 模式,不 print() 就等于丢弃该行——整行消失,不是保留原样。
- 忘记
end=''→ 行数翻倍、格式错乱 - 在
try/except中吞掉了异常,导致某文件中途退出却不报错 - 用
break或return提前退出循环 → 后续行不处理,且临时文件未完整写入,可能触发回滚(取决于系统) - Windows 下路径含空格或中文,未用原始字符串或正确转义,导致文件找不到却无提示
真正起作用的只有两件事:开 inplace=True,然后对每一行 print() 出去。其余都是围绕这两点的容错和控制。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










