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()エンコーディングパラメータの違いと不足を回避するための推奨戦略は何ですか?

open()バイト文字列をストリーミングするPython 3 スタイルのファイルハンドラーを用意して、Python 2のように動作させることはできopen()ますか?

回答:


176

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

Python 2.6および2.7のみをサポートする必要がある場合は、のio.open代わりに使用できますopenioPython 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 2014年

7
@pmdarrowこの場合も同じですが、厳密に言えば、はい。
Lennart Regebro 2014年

オプション2のバイトストリームに対して正規表現を実行できないという問題に遭遇しました;)
Jonathan Komar

3
@ macmadness86バイトの正規表現を使用する必要があります。
Lennart Regebro 2015年

4
移植方法に関する注意:「codecs.open()を使用するという古い習慣に煩わされないでください。これは、Python 2.5との互換性を維持するためにのみ必要であるためです。」docs.python.org/3/howto/pyporting.html
Al Sweigart

65

おもう

from io import open

すべきです


7
下記のLennartの応答は、codecs.openを使用するという提案とともに、2.xでioモジュールが遅いという警告と詳細を提供するので、はるかに良いと思います。
gps

2
from io import openPython 3で使用するとどうなりますか?現在、パフォーマンスは気にしていません。
マット、

8
@matth python3では、ioからのopenは組み込みのopenのエイリアスです。docs.python.org/3/library/io.html?highlight=io#io.open
mfusseneggerを

21

これが1つの方法です。

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です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.