web-dev-qa-db-ja.com

Python 3 open(encoding = "utf-8")から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()のように動作しますか?

136
Mikko Ohtamaa

1. Python 2でエンコードパラメーターを取得するには:

Python 2.6および2.7のみをサポートする必要がある場合は、openの代わりに io.open を使用できます。 ioはPython 3の新しいioサブシステムであり、Python 2,6 ans 2.7にも存在します。 Python 2.6(3.0と同様)では、pythonに純粋に実装されており、非常に遅いため、ファイルの読み取りに速度が必要な場合、これは適切なオプションではありません。

速度が必要な場合、またはPython 2.5以前をサポートする必要がある場合は、代わりに codecs.open を使用できます。また、エンコードパラメータがあり、io.openと非常によく似ていますが、行末の処理方法が異なります。

2.バイト文字列をストリーミングするPython 3 open()スタイルのファイルハンドラーを取得するには:

open(filename, 'rb')

「バイナリ」を意味する「b」に注意してください。

156
Lennart Regebro

おもう

from io import open

する必要があります。

60
mfussenegger

1つの方法を次に示します。

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

これはトリックをするかもしれません:

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は機能しないことに注意してください。

8
user2395922

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に関連するすべてを削除することです。

1
YaOzI