174

我有一个为 Python 3 构建的 Python 代码库,它使用 Python 3 风格的 open() 和 encoding 参数:

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 3open()风格的文件处理程序来流式传输字节串,所以它会像 Python 2 一样工作open()吗?

4

6 回答 6

187

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

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

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

2. 获取open()流字节串的 Python 3 样式文件处理程序:

open(filename, 'rb')

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

于 2012-06-11T06:32:41.383 回答
68

我认为

from io import open

应该做。

于 2012-06-10T18:04:28.777 回答
29

这是一种方法:

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

以下是编写时如何做同样的事情:

with open("filename.txt", "wb") as f:
    f.write(contents.encode("UTF-8"))
于 2016-11-17T15:38:29.917 回答
9

这可能会奏效:

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(如newline, closefd, )opener不起作用

于 2014-11-21T10:13:05.040 回答
2

If you are using six, you can try this, by which utilizing the latest Python 3 API and can run in both 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.')

And, Python 2 support abandon is just deleting everything related to six.

于 2019-06-10T04:51:25.233 回答
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
于 2020-08-04T14:00:50.743 回答