Unicode write()-在Python3.x中调用编码字符串

Unicode write()-在Python3.x中调用编码字符串,unicode,python-3.x,Unicode,Python 3.x,我有一个unicode字符串要写入文件 在Python 2中,我可以写: open('filename', 'w').write(s.encode('utf-8')) 但对于Python3来说,这是失败的。显然,s.encode()返回“bytes”类型的内容,write()函数不接受: TypeError: must be str, not bytes 有人知道如何将上述代码移植到Python3吗 编辑: 感谢所有建议使用二进制模式的人!很遗憾,这会导致\n字符出现问题。是否有任何方法可以

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

在Python 2中,我可以写:

open('filename', 'w').write(s.encode('utf-8'))
但对于Python3来说,这是失败的。显然,s.encode()返回“bytes”类型的内容,write()函数不接受:

TypeError: must be str, not bytes
有人知道如何将上述代码移植到Python3吗

编辑:

感谢所有建议使用二进制模式的人!很遗憾,这会导致\n字符出现问题。是否有任何方法可以实现与Python 2相同的结果(即在UTF-8中编码非ANSI字符,同时保留操作系统特定的格式副本\n)


谢谢

以二进制模式打开文件

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

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

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

您可能需要阅读该函数的手册。

您不希望这样手工编码每一条数据!只需将编码作为参数传递给
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
看看这有多容易?让流对象为您处理任何低级编码或解码


摘要:当您正在使用
编码或
解码来处理同一编码的同质流时,不要自己调用
编码或
解码。这对零增益来说太麻烦了。只需一次性使用
encoding
参数。

在3.2中没有理由不将
一起使用。另外,
f.close()
,而不是
f.close
@agf Ug,你是对的。我如何让Python警告我这些愚蠢的错误?在Perl中,我会得到“在void上下文中无用地使用常量”之类的东西。@Lennart:谢谢,但为什么它更好呢?
f
?@tchrist:是的,即使您提出错误,f也会关闭。请参阅,您不知道它何时被垃圾回收。你说得对,这对资源管理很重要。这就是为什么您应该将
一起使用的原因。我选择接受这个答案,因为它帮助我——Python新手——理解有两个有效的选项:使用文本文件,在这种情况下,我需要在
打开()时设置
编码
,或者使用二进制文件,这与我以前的情况非常相似(但在处理新行时会造成一些困难,但我想只要多做一点努力,我也可以处理它们)。到目前为止,我已经了解并欣赏了Python 3.x区分文本(
str
)和(二进制)数据(
bytes
)的方法。