【问题标题】:write()-ing an encoded string in Python 3.x在 Python 3.x 中 write()-ing 编码字符串
【发布时间】:2011-11-14 10:29:35
【问题描述】:

我有一个要写入文件的 unicode 字符串。

在 Python 2 中我可以编写:

open('filename', 'w').write(s.encode('utf-8'))

但这对于 Python 3 来说是失败的。显然,s.encode() 返回了一些“字节”类型的东西,而 write() 函数不接受:

TypeError: must be str, not bytes

有人知道如何将上述代码移植到 Python 3 吗?

编辑:

感谢所有提出使用二进制模式的人!不幸的是,这会导致 \n 字符出现问题。有什么方法可以实现与 Python 2 相同的结果(即在 UTF-8 中编码非 ANSI 字符,同时保持操作系统特定的 \n 再现)?

谢谢!

【问题讨论】:

    标签: unicode python-3.x


    【解决方案1】:

    您确实想要像这样手动编码每条数据!只需将编码作为参数传递给open,如下所示:

    #!/usr/bin/env python3.2
    
    slist = [
        "Ca\N{LATIN SMALL LETTER N WITH TILDE}on City",
        "na\N{LATIN SMALL LETTER I WITH DIAERESIS}vet\N{LATIN SMALL LETTER E WITH ACUTE}",
        "fa\N{LATIN SMALL LETTER C WITH CEDILLA}ade",
        "\N{GREEK SMALL LETTER BETA}-globulin"
    ]
    
    with open("/tmp/sample.utf8", mode="w", encoding="utf8") as f:
        for s in slist:
            print(s, file=f)
    

    现在,如果您创建了文件,您会看到它说:

    $ cat /tmp/sample.utf8
    Cañon City
    naïveté
    façade
    β-globulin
    

    您可以通过这种方式看到这些是正确的代码点:

    $ uniquote -x /tmp/sample.utf 
    Ca\x{F1}on City
    na\x{EF}vet\x{E9}
    fa\x{E7}ade
    \x{3B2}-globulin
    

    看看这有多容易?让流对象为您处理任何低级编码或解码。

    总结:当您所做的只是使用它们来处理一个同质的流时,不要自己打电话给encodedecode,而所有这些流都采用相同的编码。这对于零增益来说太麻烦了。一次性使用 encoding 参数。

    【讨论】:

    • 没有理由不在 3.2 中使用 with。另外,f.close(),而不是 f.close
    • @agf Ug,你是对的。我如何让 Python 警告我这些愚蠢的错误?在 Perl 中,我会得到“在 void 上下文中无用地使用常量”之类的东西。
    • @Lennart:谢谢,但为什么更好? f的范围控制?
    • @tchrist: 是的,即使你提出错误等 f 也会关闭。参见effbot.org/zone/python-with-statement.htmpython.org/dev/peps/pep-0343
    • 你不知道它什么时候会被垃圾回收。你是对的,这对资源管理很重要。这就是为什么你应该使用with
    【解决方案2】:

    以二进制模式打开文件,就更改而言,这是侵入性最小的方式。

    另一方面,您可以使用 open() 设置输出文件编码,并完全避免显式字符串编码。

    您可能需要阅读open() 函数的手册。

    【讨论】:

    • 我选择接受这个答案,因为它帮助我 - Python 新手 - 了解有两个有效选项:使用 text 文件,在这种情况下我需要在open()-ing 文件时设置encoding,或者使用 binary 文件,这与我以前的文件非常相似(但在处理换行符时会遇到一些困难,但我猜想我也可以花一些额外的努力来治疗它们)。到目前为止,我已经了解并欣赏 Python 3.x 区分 text (str) 和 (binary) data (bytes) 的方式。
    【解决方案3】:

    以二进制模式打开文件

    open('filename', 'wb').write(s.encode('utf-8'))
    

    【讨论】:

      猜你喜欢
      • 2019-09-27
      • 1970-01-01
      • 2013-10-17
      • 1970-01-01
      • 2015-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多