Pythonでのopenとcodecs.openの違い


93

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

f = open(filename)

そして

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

いつがcodecs.open望ましいopenですか?


44
は引数を取得するcodecs.open()ため、3.xでは廃止されていることに注意してください。open()encoding
Ignacio Vazquez-Abrams

3つ目の方法もあります(少なくともPython 2.xでは): `f = file(filename) '
Adam Parkin

1
@ IgnacioVazquez-Abrams codecs.open()廃止されたリンクはありますか?私はこれをpython3のドキュメントでは考えていません:docs.python.org/3.7/library/codecs.html
varela

1
@varela:あなたが言及したPythonのドキュメントページには次のように書かれています:「組み込みのopen()と関連するioモジュールは、エンコードされたテキストファイルを操作するための推奨アプローチです」
Luciano Ramalho

回答:


82

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

ここで、元の質問について:Python 2でテキスト(「プレーンテキスト」、HTML、XML、JSONを含む)を読み取るときは、常にio.open()明示的なエンコーディングで使用する必要があります。open()、Python 3で明示的なエンコーディングを使用する必要があります。そうすることで、正しく取得できますUnicodeをデコードするか、すぐにエラーを取得して、デバッグをはるかに簡単にします。

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

純粋なASCIIは実際のオプションではないためopen()、明示的なエンコーディングなしでバイナリファイルを読み取る場合にのみ役立ちます。


5
@ForeverWintr答えはそこにかなり明確にありio.open()ますopen()。テキストに使用し、バイナリのみに使用してください。つまり、それcodecs.open()はまったく好ましくないということです。
Bdoserror 2017

2
@Bdoserror、そこには明らかに答えがありますが尋ねられた質問に対する答えではありません。問題は、との違いについてでopenありcodecs.open、具体的には、後者が前者よりも好ましい場合です。言及ほど多くcodecs.openない答えはその質問に答えることができません。
ForeverWintr 2017

3
@ForeverWintr OPが間違った質問をした場合(つまり、codecs.open()使用することが正しいという前提で)、いつ使用するかについての「正しい」回答はありません。答えはio.open()代わりに使用することです。「レンチを使って釘を壁に打ち込む必要があるのはいつ?」と尋ねるようなものです。正解は「ハンマーを使う」です。
Bdoserror 2017

20

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

ASCIIはUTF-8として扱うことができるため、私の経験では、デフォルトのエンコーディングとして「utf-8」を使用する方が安全なデフォルトの選択になる傾向がありますが、その逆は当てはまりません。そして、私が入力がASCIIであることを本当に知っているような場合でもcodecs.open、私は「明示的なものは暗黙的なものより優れている」と確信しいるため、私はまだそうしています。

**-Python 2.xでは、質問へのコメントがPython 3にopen置き換わったためcodecs.open


私が実際に得られないのopenは、ユニコードセットのUTF-8エンコードされた非ラテン文字をうまく処理できることがあり、誤って失敗することがあります...
cedbeu

これは私には理にかなっています。io.open私がpython 2.7.5で見ることができるものからエンコードパラメータを取得しません
radtek

1
@radtek、これは文書化されていないことは正しいです。ただし(少なくとも2.7.12では)パラメータとパラメータをio.open受け入れencodingnewlineそれらをPython 3と同様に解釈します。異なりcodecs.open、で開かれたファイルがio.open発生しますTypeError: write() argument 1 must be unicode, not str、あなたが書き込みをしようとした場合でも、Pythonの2.7でstrbytesそれまで)。で開いたファイルは、codecs.open代わりにへの暗黙の変換を試みunicode、しばしばを混乱させUnicodeDecodeErrorます。
jochietoch

9

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

たとえば、Unicode文字列があり、次のような場合に問題が発生します。

>>> 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.openASCII以外の文字が渡されるバイト文字列は好きではありません。

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)

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

ASCII以外の文字が含まれる可能性のあるバイト文字列ではなく、Unicode文字列を指定するように注意してください。


2番目の例を説明できますか?最初の例と同じように見えますが、なぜ結果が異なるのでしょうか?
Chris Johnson、

u''最初の例でのの使用に注意してください。これは、バイト文字列ではなくUnicode文字列を作成したことを意味します。これが2つの例の違いです。2番目の例では、バイト文字列を作成し、それらの1つをファイルに書き込んで問題ありません。ASCII以外の文字を使用している場合、Unicode文字列は適切ではありません。
Mandible79 2017

7

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


15
どういうわけか、すべてのテキストファイルは特定のエンコーディングを持っていると思います(:
cedbeu

5

codecs.openPython 2、組み込みのopenのインターフェースがはるかにシンプルで機能が少なかった時代の名残だと思います。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.open同じですbuilt-in open

注意:

との間にも構文上の違いがcodecs.openありio.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)

構文が異なるだけでなくcodecs.openio.open異なるタイプのオブジェクトを返します。また、codecs.open常にバイナリモードでファイルを操作します。
wombatonfire

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

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

python 3しかし、open同じことをしio.openて、代わりに使用することができます。

注: codecs.openは、Python 2.6での導入後に廃止され、置き換えられる予定です。コードが以前のバージョンのpythonと互換性が必要な場合にのみ使用します。Pythonのコーデックとユニコードの詳細については、Unicode HOWTOを参照してください。io.open


1. io.openまたはでバイナリモードでファイルを開けないのはなぜcodecs.openですか?2. codecs.openは非推奨ではありません。リンク先のページの説明をお読みください。
wombatonfire

良い点!1.どちらでも使用できますが、python 2.5以前を使用しているのでない限り、codecs.openに対して再度アドバイスをします。2.私は回答を更新して、サポート終了がすぐにではなく将来的に行われることを反映しました。
wihlke

3

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


0

.asmファイルを開いて処理する状況にありました。

#https://docs.python.org/3/library/codecs.html#codecs.ignore_errors
#https://docs.python.org/3/library/codecs.html#codecs.Codec.encode
with codecs.open(file, encoding='cp1252', errors ='replace') as file:

それほど問題なく、ファイル全体を読むことができますが、何か提案はありますか?

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