V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Leon6868
V2EX  ›  Python

Python xml 模块的一个坑

  •  
  •   Leon6868 · 2020-08-17 11:16:04 +08:00 via Android · 1713 次点击
    这是一个创建于 1551 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这个坑出在文件编码上。
    当你使用 doc.writexml(f, encoding="utf-8") 时,这里的 encoding 只会在 xml 标签上添加encoding="utf-8"标签,而 xml 文件内容本身的编码,是没有改变的。
    这就意味着,如果你写入中文,无论你怎么 encode 、decode,最终只会得到一个充满乱码的 xml 文件。
    正确的写法是这样:

    with open(file, "w", encoding="utf-8") as f:
        doc.writexml(file, encoding="utf-8")
    

    在 open 方法里面加入 encoding="utf-8",才会改变文件的编码。

    这个坑还没有人专门写,所以记录一下,希望能帮到一些人。

    10 条回复    2020-08-20 16:16:37 +08:00
    learningman
        1
    learningman  
       2020-08-17 11:47:43 +08:00
    说明看文档要仔细
    Jirajine
        2
    Jirajine  
       2020-08-17 11:51:34 +08:00 via Android
    Python 的这个编码问题一直都很坑,别的大多数语言字符串都是 utf-8 encoded bytes,唯独 Python 的字符串是未编码的,而且编码时默认还是平台的编码而不是一律 utf-8 。
    Nitroethane
        3
    Nitroethane  
       2020-08-17 11:55:03 +08:00
    这怕是你没仔细看文档吧,文档里清楚地写了 “For the Document node, an additional keyword argument encoding can be used to specify the encoding field of the XML header.”,人可没说是指定文件内容的编码
    abersheeran
        4
    abersheeran  
       2020-08-17 12:59:17 +08:00
    我个人觉得是你不懂 open 这个内置函数以及文件编码导致的。
    abersheeran
        5
    abersheeran  
       2020-08-17 12:59:48 +08:00
    @Jirajine 兄弟,这都 2020 年了,你还在这念 Python2 的经?
    fhsan
        6
    fhsan  
       2020-08-17 13:08:23 +08:00
    都什么年代了,还分不清编码问题,python 获取当前操作系统编码,如果你想保持一致,write 、open 文本文件都要指定编码。统一编码是不可能的
    Jirajine
        7
    Jirajine  
       2020-08-17 13:34:44 +08:00 via Android
    @abersheeran 说的就是 Python3 啊,别的语言 string 可以直接当成 utf-8 encoded bytes 用,唯独 Python 需要额外把 string encode 成 bytes,并且默认参数在 Windows 下还不是 utf-8 。
    至于内部如何表示那是另一回事了,string 暴露出来的接口就是未编码的字符串对象,需要调用 encode()才会变成 bytes 。
    abersheeran
        8
    abersheeran  
       2020-08-17 19:47:48 +08:00
    @Jirajine 你说的别的语言怕是 C 这种弱类型吧。哪个强类型语言还能把 string 当 bytes 用的?你举个例子。
    Jirajine
        9
    Jirajine  
       2020-08-17 20:00:44 +08:00 via Android
    @abersheeran golong 、rust 都是这样。
    我上面的描述不太准确,不是把 string 当 bytes 用,而是 string 就是 utf-8 encoded bytes 。
    因此把 string 往文件写不需要指定编码,string 就是二进制的 bytes,写二进制数据当然不需要指定编码。
    abersheeran
        10
    abersheeran  
       2020-08-20 16:16:37 +08:00
    @Jirajine Python3 的 str 不就是默认 utf8 的?往文件里写需要指定编码是因为默认使用你操作系统的编码打开的,因为你是中国人,win 选择中文,所以默认是 gbk 。但 Windows10 有强制 utf8 的选项,你要是不怕某些垃圾软件不兼容 utf8,你可以开开,就没这个问题了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2857 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 02:41 · PVG 10:41 · LAX 18:41 · JFK 21:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.