簡體   English   中英

將 Python 3 open(encoding="utf-8") 向后移植到 Python 2

[英]Backporting Python 3 open(encoding=“utf-8”) to Python 2

我有一個為 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()嗎?

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. 要獲得一個 Python 3 open()樣式的文件處理程序,它可以傳輸字節串:

open(filename, 'rb')

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

我認為

from io import open

應該做。

這是一種方法:

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"))

這可能會奏效:

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不起作用

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

不是一般的答案,但對於您對默認的 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM