web-dev-qa-db-ja.com

Pythonのopenとcodecs.openの違い

Pythonでテキストファイルを開くには、2つの方法があります。

f = open(filename)

そして

import codecs
f = codecs.open(filename, encoding="utf-8")

時である codecs.openopenよりも望ましいですか?

77
BlogueroConnor

Python 2.6以降、io.open()を使用することをお勧めします。これは、現在廃止されているcodecs.open()のように、encoding引数も取ります。 Python 3では、io.openopen()ビルトインのエイリアスです。 io.open()はPython 2.6およびPython 3.4を含むそれ以降のすべてのバージョンで動作します。ドキュメントを参照してください: http://docs.python.org/3.4/library/io.html

さて、元の質問:Python 2でtext(「プレーンテキスト」、HTML、XML、JSONを含む)を読むときalwaysを使用する必要がありますio.open()明示的なエンコード、またはopen()での明示的なエンコードPython 3.これを行うと、Unicodeが正しくデコードされるか、すぐにエラーが発生します。デバッグがずっと簡単になります。

純粋なASCII "プレーンテキスト"は、遠い昔からの神話です。適切な英語のテキストは、中括弧、em-ダッシュ、箇条書き、ユーロ(ユーロ記号)、分音記号(¨)を使用します。ナイーブにしないでください! (そして、ファサードのデザインパターンを忘れないでください!)

純粋なASCIIは実際のオプションではないため、明示的なエンコードなしのopen()onlybinaryファイルの読み取りに役立ちます。

73
Luciano Ramalho

個人的には、Ialwayscodecs.openopen **を使用する必要があることが明確に識別されていない限り。理由は、プログラムにutf-8入力が忍び込んだことでかまれたことが何度もあったからです。 「ああ、私はそれが常にアスキーであることを知っているだけです」という仮定はしばしば破られる傾向があります。

ASCIIはUTF-8として扱うことができますが、その逆は当てはまりません。入力がASCIIであることを本当に知っている場合は、codecs.open私は "暗黙的よりも明示的である" を固く信じています。

**-Python 2.x、質問に対するコメントはPython 3 opencodecs.open

18
Adam Parkin

Python 2にはUnicode文字列とバイト文字列があります。バイト文字列を使用するだけの場合、open()で開いたファイルの読み取り/書き込みができます。結局、文字列バイトだけです。

たとえば、ユニコード文字列があり、次のことを行う場合に問題が発生します。

>>> example = u'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

したがって、ここでは明らかにutf-8でUnicode文字列を明示的にエンコードするか、codecs.openを使用して透過的に実行します。

バイトストリングのみを使用している場合、問題はありません。

>>> example = 'Μου αρέσει Ελληνικά'
>>> open('sample.txt', 'w').write(example)
>>>

+演算子を使用してUnicodeとバイト文字列を連結すると、Unicode文字列が取得されるため、これよりも複雑になります。簡単に噛まれます。

また、codecs.openは、非ASCII文字が渡されるバイト文字列を好みません:

codecs.open('test', 'w', encoding='utf-8').write('Μου αρέσει')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/codecs.py", line 691, in write
    return self.writer.write(data)
  File "/usr/lib/python2.7/codecs.py", line 351, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)

入力/出力の文字列に関するアドバイスは、通常、「できるだけ早くユニコードに変換し、できるだけ遅くバイト文字列に戻す」ことです。 codecs.openを使用すると、後者を非常に簡単に行うことができます。

ASCII以外の文字を含む可能性のあるバイト文字列ではなく、ユニコード文字列を指定していることに注意してください。

8
Mandible79

特定のエンコーディングを持つファイルを開く必要がある場合は、codecsモジュールを使用します。

6
Geo

codecs.openは、組み込みのopenのインターフェイスがはるかに単純で機能が少なかったPython 2時代の名残です。 Python 2、組み込みのopenはエンコード引数を取りません。したがって、バイナリモードまたはデフォルトのエンコード以外を使用する場合、codecs.openは使用されることになっています。

Python 2.6では、ioモジュールが少し簡単にするために役立ちました。公式によると ドキュメント

New in version 2.6.

The io module provides the Python interfaces to stream handling.
Under Python 2.x, this is proposed as an alternative to the
built-in file object, but in Python 3.x it is the default
interface to access files and streams.

そうは言っても、現在のシナリオでcodecs.openについて考えることができる唯一の用途は、後方互換性のためです。他のすべてのシナリオ(Python <2.6)を使用していない場合)では、io.openを使用することをお勧めします。また、Python 3.xでは、io.openbuilt-in openと同じです。

注:

codecs.openio.openの間にも構文上の違いがあります。

codecs.open

open(filename, mode='rb', encoding=None, errors='strict', buffering=1)

io.open

open(file, mode='r', buffering=-1, encoding=None,
     errors=None, newline=None, closefd=True, opener=None)
5
heretolearn

テキストファイルを使用していて、Unicodeオブジェクトへの透過的なエンコードおよびデコードが必要な場合。

3
Cat Plus Plus
  • バイナリファイルをロードする場合は、f = io.open(filename, 'b')を使用します。

  • テキストファイルを開くには、常に明示的なエンコーディングでf = io.open(filename, encoding='utf-8')を使用します。

python 3では、openio.openと同じことを行い、代わりに使用できます。

注:codecs.openは、 非推奨 になり、 io.openpython 2.6で紹介した後。コードを以前のpythonバージョンと互換性が必要な場合にのみ使用します。コーデックとUnicodeの詳細についてはpythonを参照してください Unicode HOWTO

2
wihlke