python读取gbk编码xml文件需显式指定encoding='gbk',避免默认utf-8导致乱码;推荐用open()读取后交et.parse()解析,并注意bom、编码混杂等问题。

Python读取GBK编码的XML文件时,核心是明确指定编码格式,避免默认用UTF-8解码导致乱码或报错。关键不在XML解析逻辑本身,而在文件打开和字符流传递环节。
用open()显式指定encoding='gbk'再传给xml.etree.ElementTree
ElementTree默认不处理编码声明(如),它依赖输入字节流或字符串的正确性。推荐做法是先用内置open()以gbk编码读取为字符串,再交给ET解析:
- 确保文件真实保存为GBK(不是GB2312或GBK变种如GB18030,如有疑问可用notepad++查看编码)
- 代码示例:
import xml.etree.ElementTree as ET <p>with open('data.xml', 'r', encoding='gbk') as f: tree = ET.parse(f) # 或 ET.fromstring(f.read()) root = tree.getroot() - 如果遇到UnicodeDecodeError: 'gbk' codec can't decode byte,说明文件里混入了非GBK字节(比如BOM、UTF-8残留或编辑器自动转码),可改用errors='ignore'或errors='replace'容错:
with open('data.xml', 'r', encoding='gbk', errors='ignore') as f:
用codecs.open()兼容老版本Python或需更细粒度控制
Python 2.x不支持open()的encoding参数,或你需要统一处理多种编码时,可用codecs模块:
import codecswith codecs.open('data.xml', 'r', 'gbk') as f:- 后续仍传给ET.parse()即可,效果等同于第一种方法
- 注意:codecs.open返回的是文本流,不是bytes流,无需额外decode
解析含XML声明encoding="GBK"的文件时不要依赖它
XML声明中的encoding属性仅是提示,ElementTree不会自动按该值重新解码。它只对从bytes读取且未指定编码时起作用(如ET.parse(io.BytesIO(b'...'))),但这种用法易出错,不推荐。
立即学习“Python免费学习笔记(深入)”;
- 错误示范(可能失败):
with open('data.xml', 'rb') as f: # 读成bytes<br> tree = ET.parse(f) # ET会尝试读声明,但实际环境常不准 - 正确思路:始终主动控制解码过程,把编码责任收归Python层,而非交给XML解析器猜测
- 若必须用bytes输入(如网络响应),请手动decode后再解析:
content = response.content.decode('gbk')<br> root = ET.fromstring(content)
写回GBK编码XML时保持一致性
修改后保存为GBK,需手动写入XML声明并指定encoding:
- ET.write()默认输出UTF-8,且不加XML声明。要输出GBK,需自己拼接:
tree.write('output.xml', encoding='gbk', xml_declaration=True)- 注意:Python 3.9+支持该写法;旧版本需先tostring再手动写文件:
xml_str = ET.tostring(root, encoding='gbk').decode('gbk')<br> with open('output.xml', 'w', encoding='gbk') as f:<br> f.write('<?xml version="1.0" encoding="GBK"?>\n' + xml_str)










