Python 中 open 和 codecs.open 的区别

用 Python 打开文本文件有两种方法:

f = open(filename)

还有

import codecs
f = codecs.open(filename, encoding="utf-8")

什么时候 codecs.openopen更好?

90608 次浏览

当需要打开具有某种编码的文件时,可以使用 codecs模块。

当您使用文本文件并希望透明编码和解码为 Unicode 对象时。

就个人而言,我 一直都是使用 codecs.open,除非有一个明确的确定需要使用 open * * 。原因在于,有很多次当我被 utf-8输入溜进我的程序时咬了一口。“哦,我只知道它将永远是 ascii”往往是一个经常被打破的假设。

根据我的经验,假设‘ UTF-8’作为默认编码往往是一个更安全的默认选择,因为 ASCII 可以被视为 UTF-8,但相反的情况并非如此。在这些情况下,当我真正做 know时,输入是 ASCII,那么我仍然做 codecs.open,因为我是 “显性比隐性好”的坚定信徒。

* *-在 Python 2.x 中,如 Python 3 open中关于问题的注释所述,codecs.open被取代

在 Python2中有 unicode 字符串和 bytestring。如果只使用字节串,那么可以对用 open()打开的文件进行读/写操作。毕竟,字符串只是字节。

当您有一个 unicode 字符串并执行以下操作时,问题就出现了:

>>> example = u'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

所以很明显,这里您要么显式地将 unicode 字符串编码为 utf-8,要么使用 codecs.open透明地完成这项工作。

如果你只使用字节串,那么没有问题:

>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>

它比这更复杂,因为当您将 unicode 和 bytestring 字符串与 +操作符连接时,您将得到一个 unicode 字符串。很容易被咬到。

codecs.open也不喜欢传入非 ASCII 字符的字节串:

codecs.open('test', 'w', encoding='utf-8').write('Μου αρέσει')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/codecs.py", line 691, in write
return self.writer.write(data)
File "/usr/lib/python2.7/codecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)

关于输入/输出字符串的建议通常是“尽早转换为 unicode,尽可能晚地转换回字节串”。使用 codecs.open可以很容易地完成后者。

Just be careful that you are giving it unicode strings and not bytestrings that may have non-ASCII characters.

自 Python 2.6以来,一个好的实践是使用 io.open(),它也接受 encoding参数,就像现在已经过时的 codecs.open()。在 Python 3中,io.open是内置 open()的别名。因此,io.open()可以在 Python 2.6和所有更高版本中工作,包括 Python 3.4。参见文档: http://docs.python.org/3.4/library/io.html

现在,回到最初的问题: 在读取 Python 2中的 短信(包括“纯文本”、 HTML、 XML 和 JSON)时,您应该使用带有显式编码的 io.open(),或者在 Python 3中使用带有显式编码的 open()。这样做意味着您可以正确解码 Unicode,或者立即得到一个错误,从而使调试更加容易。

纯 ASCII“纯文本”是一个来自遥远过去的神话。正确的英语文本使用了卷曲的引号、 em-破折号、项目符号、 something (欧元符号) ,甚至 diaeresis ()。别天真了!(我们不要忘记正面设计模式!)

因为纯 ASCII 不是一个真正的选项,没有显式编码的 open()对于读取 二进制文件是 only有用的。

  • 如果要加载二进制文件,请使用 f = io.open(filename, 'b').

  • 对于打开文本文件,始终使用带有显式编码的 f = io.open(filename, encoding='utf-8')

然而,在 python 3中,openio.open做同样的事情,可以用来代替。

注: 在 Python 2.6中引入 codecs.open后,codecs.open计划成为 不赞成并被 io.open所取代。只有在代码需要与早期的 Python 版本兼容时,我才会使用它。有关 python 中的 codecs 和 unicode 的更多信息,请参见 Unicode 如何操作

我认为,codecs.open只是 Python 2时代的残余,当时内置的 open 具有更简单的接口和更少的功能。在 Python 2中,内置的 open不接受编码参数,所以如果您想使用二进制模式或默认编码以外的其他方式,那么应该使用 codecs.open。

In Python 2.6, the io module came to the aid to make things a bit simpler. 根据官方的 < a href = “ https://docs.python.org/2/library/io.html”rel = “ nofollow noReferrer”> 文档

New in version 2.6.


The io module provides the Python interfaces to stream handling.
Under Python 2.x, this is proposed as an alternative to the
built-in file object, but in Python 3.x it is the default
interface to access files and streams.

尽管如此,我认为在当前的情况下,codecs.open的唯一用途是向下兼容。在所有其他场景中(除非使用 Python < 2.6) ,最好使用 io.open。也在 Python 3.x io.open是相同的 built-in open

注:

codecs.openio.open在句法上也有区别。

返回文章页面

open(filename, mode='rb', encoding=None, errors='strict', buffering=1)

返回文章页面

open(file, mode='r', buffering=-1, encoding=None,
errors=None, newline=None, closefd=True, opener=None)