向后移植将Python 3 open(encoding =“ utf-8”)移植到Python 2


152

我有一个为Python 3构建的Python代码库,它使用带有编码参数的Python 3样式的open():

https://github.com/miohtama/vvv/blob/master/vvv/textlineplugin.py#L47

    with open(fname, "rt", encoding="utf-8") as f:

现在,我想将此代码反向移植到Python 2.x,这样我将拥有一个可用于Python 2和Python 3的代码库。

建议的解决方法是什么 open()差异和缺乏编码参数的什么?

我可以使用Python 3 open()样式的文件处理程序来流字节字符串,以便像Python 2那样工作open()吗?

Answers:


176

1.在Python 2中获取编码参数:

如果您只需要支持Python 2.6和2.7,则可以使用io.open代替openio是Python 3的新io子系统,它也存在于Python 2,6 ans 2.7中。请注意,在Python 2.6(以及3.0)中,它是完全在python中实现的,并且运行速度非常慢,因此,如果您需要快速读取文件,则不是一个好的选择。

如果需要速度,并且需要支持Python 2.6或更早版本,则可以codecs.open改用。它也有一个编码参数,io.open除了它以不同的方式处理行尾之外,它与之非常相似。

2.要获取open()可流字节串的Python 3 样式文件处理程序,请执行以下操作:

open(filename, 'rb')

注意“ b”,意思是“二进制”。


11
“ b”实际上表示二进制模式,而不是字节。请参阅docs.python.org/3/library/functions.html#open
pmdarrow

7
@pmdarrow在这种情况下也是一样,但严格来说,是的。
Lennart Regebro 2014年

我遇到了一个问题,即您无法在选项2的字节流上运行正则表达式;)
Jonathan Komar 2015年

3
@ macmadness86您需要使用字节正则表达式。
Lennart Regebro 2015年

4
移植howto上的一条注释:“不要为使用codecs.open()而过时的做法打扰,因为只有这样才能保持与Python 2.5的兼容性。” docs.python.org/3/howto/pyporting.html
Al Sweigart

65

我认为

from io import open

应该做。


7
我认为Lennart在下面的响应会更好,因为它提供了更多的解释,并且有关io模块在2.x中运行缓慢的警告以及使用codecs.open的建议。
gps 2012年

2
如果from io import open在Python 3中使用会发生什么?我目前不关心性能。
2016年

8
@matth在python3中,从io打开是内置open的别名。参见docs.python.org/3/library/io.html?highlight=io#io.open
mfussenegger '16

20

这是一种方法:

with open("filename.txt", "rb") as f:
    contents = f.read().decode("UTF-8")

4
如果您有其他不同的计划,这显然将无法正常工作f
user5359531

8

这可能会达到目的:

import sys
if sys.version_info[0] > 2:
    # py3k
    pass
else:
    # py2
    import codecs
    import warnings
    def open(file, mode='r', buffering=-1, encoding=None,
             errors=None, newline=None, closefd=True, opener=None):
        if newline is not None:
            warnings.warn('newline is not supported in py2')
        if not closefd:
            warnings.warn('closefd is not supported in py2')
        if opener is not None:
            warnings.warn('opener is not supported in py2')
        return codecs.open(filename=file, mode=mode, encoding=encoding,
                    errors=errors, buffering=buffering)

然后,您可以使用python3方式保留代码。

请注意,一些API一样newlineclosefdopener不工作


1
您可以反转条件以避免这种情况pass
bfontaine

2

如果您使用six,则可以尝试使用最新的Python 3 API并可以在Python 2/3中运行:

import six

if six.PY2:
    # FileNotFoundError is only available since Python 3.3
    FileNotFoundError = IOError
    from io import open

fname = 'index.rst'
try:
    with open(fname, "rt", encoding="utf-8") as f:
        pass
        # do_something_with_f ...
except FileNotFoundError:
    print('Oops.')

而且,放弃Python 2支持只是删除与相关的所有内容six

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.