xml.etree.ElementTree.tostring()在Python 3中默认返回bytes而非str,需显式指定encoding="unicode"才返回str;写入文件时须匹配open模式(文本模式配str,二进制模式配bytes)。

tostring() 默认返回 bytes,不是 str
调用 xml.etree.ElementTree.tostring() 时,Python 3 下默认返回 bytes 对象,不是 Unicode 字符串(str)。这是最常踩的坑:直接 print 或拼接会报 TypeError: can't concat bytes to str,或者写入文件时抛出 UnicodeEncodeError。
根本原因在于 XML 序列化必须明确编码格式(如 utf-8),而 bytes 是编码后的原始字节,str 才是解码后的文本。tostring 不做隐式解码 —— 它只负责“序列化”,不负责“转成 Python 字符串”。
- 不指定
encoding参数 → 返回bytes(默认 utf-8 编码) - 显式传
encoding="unicode"→ 返回str(即 Unicode 字符串) - 传其他编码如
"utf-8"、"iso-8859-1"→ 仍返回bytes
示例:
from xml.etree import ElementTree as ET
root = ET.fromstring("<root><child>café</child></root>")
print(type(ET.tostring(root))) # <class 'bytes'>
print(type(ET.tostring(root, encoding="unicode"))) # <class 'str'>写入文件时 encoding 参数不能只靠 tostring 决定
很多人以为只要 tostring 返回 str 就能直接写入文件,但实际还要看 open() 的模式。如果用 encoding="unicode" 得到 str,就必须用文本模式("w")打开文件;若 tostring 返回 bytes,就必须用二进制模式("wb")。
立即学习“Python免费学习笔记(深入)”;
-
ET.tostring(..., encoding="unicode")+open(..., "w", encoding="utf-8")✅ -
ET.tostring(..., encoding="utf-8")+open(..., "wb")✅ -
ET.tostring(..., encoding="utf-8")+open(..., "w")❌ 报错:expected str, not bytes
常见错误现象:TypeError: write() argument must be str, not bytes 或反过来 TypeError: a bytes-like object is required, not 'str'。
encoding="unicode" 的兼容性与性能代价
encoding="unicode" 看似省事,但它在 CPython 中是纯 Python 实现的 fallback 路径,比原生 bytes 输出慢 2–5 倍(尤其对大 XML)。而且它只在 Python 3.8+ 稳定支持;3.7 及更早版本行为不一致,某些情况下仍可能返回 bytes。
- 生产环境建议优先用
encoding="utf-8"+open(..., "wb")组合 - 调试或模板拼接时用
encoding="unicode"更方便,但别用于高频或大数据量场景 - 注意:即使指定了
encoding="unicode",XML 声明里仍不会自动加encoding="UTF-8"—— 那是xml_declaration=True控制的
中文乱码的真正源头常不在 tostring
很多用户看到输出里中文变 或 \uXXXX,第一反应是 tostring 编码错了,但更大概率是后续环节没对齐:比如用 encoding="utf-8" 得到 bytes,却用 print() 直接输出(终端编码不匹配),或写入文件后用 GBK 编辑器打开。
- 验证 bytes 内容是否正确:用
my_bytes.decode("utf-8")看是否报错 - 检查终端/编辑器编码设置,而非改 tostring 参数
- XML 声明中的 encoding 属性(如
<?xml version='1.0' encoding='utf-8'?>)只是提示,不影响 tostring 输出内容
tostring 本身不“导致”乱码,它只是忠实地按你指定的方式编码。问题总出在“编码输出”和“解码消费”两端不匹配。










