向Python 2反向移植Python 3(encoding =“utf-8”)

时间:2012-06-10 18:03:29

标签: python python-2.7 python-3.x

我有一个为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()一样工作吗?

6 个答案:

答案 0 :(得分:153)

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

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

如果您需要速度,或者需要支持Python 2.5或更早版本,则可以使用codecs.open代替。它还有一个编码参数,与io.open非常相似,只是它以不同的方式处理行结尾。

2。获取Python 3 open()样式文件处理程序,它处理字节串:

open(filename, 'rb')

注意'b',意思是'二进制'。

答案 1 :(得分:60)

我认为

from io import open

应该这样做。

答案 2 :(得分:16)

以这种方式:

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

答案 3 :(得分: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方式保存代码。

请注意,newlineclosefdopener等某些API不起作用

答案 4 :(得分:1)

如果您使用的是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相关的所有内容。

答案 5 :(得分:0)

不是一个一般性的答案,但是对于您对默认的python 2编码感到满意,但又想为python 3指定utf-8的特定情况可能有用:

if sys.version_info.major > 2:
    do_open = lambda filename: open(filename, encoding='utf-8')
else:
    do_open = lambda filename: open(filename)

with do_open(filename) as file:
    pass