Python3.9使用fileinput模块遇编码及参数错误求助
问题解决:Python 3.9 fileinput模块的编码错误与参数问题
错误原因分析
- TypeError:Python 3.9的
fileinput.FileInput构造函数不支持直接传入encoding参数,该参数是Python 3.10版本才新增的特性。 - UnicodeDecodeError:你的XML文件编码并非标准UTF-8,大概率是带BOM的UTF-8(0xef是UTF-8 BOM的起始字节)或GBK等中文编码,导致用UTF-8解码失败。
解决方案
步骤1:替换encoding参数为openhook(解决TypeError)
在Python 3.9中,需通过fileinput.hook_encoded()作为openhook参数来指定文件编码,而非直接传encoding。
步骤2:匹配文件实际编码(解决UnicodeDecodeError)
优先尝试以下常见编码:
utf-8-sig:适配带BOM的UTF-8文件(针对你遇到的0xef字节问题最可能有效)gbk:中文Windows环境下的常见编码- 若不确定编码,可使用
chardet库自动检测(需先执行pip install chardet安装)
修改后的代码示例
示例1:针对带BOM的UTF-8文件
import fileinput import os FILENAME = [] # 修复:原代码只收集文件名,子目录文件会找不到,需拼接完整路径 for root, dirs, files in os.walk(r'.', topdown=False): for filename in files: if filename.endswith('.xml'): full_path = os.path.join(root, filename) FILENAME.append(full_path) print(full_path) codeskin = input('Enter Code:') Prefab = 'prefab_skill_effects/hero_skill_effects/' codeskinmod = 'prefab_skill_effects/hero_skill_effects/' Word = Prefab + codeskin CarNew = input('Enter the Character To Replace:') CarNews = codeskinmod + CarNew # 用hook_encoded指定编码,替代直接传encoding参数 with fileinput.FileInput(FILENAME, inplace=True, backup='.bak', openhook=fileinput.hook_encoded('utf-8-sig')) as file: for line in file: print(line.replace(Word, CarNews), end='') # with语句会自动关闭文件,无需手动调用file.close()
示例2:自动检测文件编码
import fileinput import os import chardet # 检测单个文件的编码 def detect_encoding(file_path): with open(file_path, 'rb') as f: result = chardet.detect(f.read()) return result['encoding'] FILENAME = [] for root, dirs, files in os.walk(r'.', topdown=False): for filename in files: if filename.endswith('.xml'): full_path = os.path.join(root, filename) FILENAME.append(full_path) print(full_path) codeskin = input('Enter Code:') Prefab = 'prefab_skill_effects/hero_skill_effects/' codeskinmod = 'prefab_skill_effects/hero_skill_effects/' Word = Prefab + codeskin CarNew = input('Enter the Character To Replace:') CarNews = codeskinmod + CarNew # 自定义openhook,根据每个文件的编码打开 def custom_openhook(filename, mode): encoding = detect_encoding(filename) return open(filename, mode, encoding=encoding, errors='ignore') with fileinput.FileInput(FILENAME, inplace=True, backup='.bak', openhook=custom_openhook) as file: for line in file: print(line.replace(Word, CarNews), end='')
内容的提问来源于stack exchange,提问作者Khánh Đàm
相关产品推荐
相关产品推荐

