私はテキストファイルを読んでいます:
f = open('data.txt')
data = f.read()
ただし、data
変数の改行は LF ('\n') に正規化されますが、ファイルには CRLF ('\r\n') が含まれます。
ファイルをそのまま読み取るようにPythonに指示するにはどうすればよいですか?
私はテキストファイルを読んでいます:
f = open('data.txt')
data = f.read()
ただし、data
変数の改行は LF ('\n') に正規化されますが、ファイルには CRLF ('\r\n') が含まれます。
ファイルをそのまま読み取るようにPythonに指示するにはどうすればよいですか?
Python 2.x の場合:
f = open('data.txt', 'rb')
ドキュメントが言うように:
デフォルトでは、テキスト モードを使用します。これは、'\n' 文字を書き込み時にプラットフォーム固有の表現に変換し、読み取り時に戻す場合があります。したがって、バイナリ ファイル
'b'
を開くときは、ファイルをバイナリ モードで開くために mode 値に追加する必要があります。これにより、移植性が向上します。(追加'b'
は、バイナリ ファイルとテキスト ファイルを異なる方法で処理しないシステムでも有用であり、ドキュメントとして機能します。)
Python 3.x には、次の 3 つの代替手段があります。
f1 = open('data.txt', 'rb')
これにより、改行は変換されずに残りますが、bytes
代わりにも返されます。これは、自分str
で明示的decode
に Unicode にする必要があります。(もちろん、2.x バージョンでは、Unicode が必要な場合は手動でデコードする必要のあるバイトも返されましたが、2.x ではそれがstr
オブジェクトであり、3.xstr
では Unicode です。)
f2 = open('data.txt', 'r', newline='')
これは を返しstr
、改行を未翻訳のままにします。ただし、2.x の同等物とは異なり、readline
フレンドは'\r\n'
通常の文字の後に改行が続くのではなく、改行として扱われます。通常、これは問題になりませんが、問題がある場合は覚えておいてください。
f3 = open('data.txt', 'rb', encoding=locale.getpreferredencoding(False))
これは改行を 2.x のコードとまったく同じように扱いstr
、デフォルトをすべて使用した場合と同じエンコーディングを使用して返しますが、現在の 3.x では有効ではなくなりました。
ストリームから入力を読み取るときに、改行が None の場合、ユニバーサル改行モードが有効になります。入力の行は '\n'、'\r'、または '\r\n' で終わることができ、これらは呼び出し元に返される前に '\n' に変換されます。'' の場合、ユニバーサル改行モードが有効になりますが、行末は翻訳されずに呼び出し元に返されます。
明示的なエンコーディングを指定する必要がある理由f3
は、ファイルをバイナリ モードで開くと、デフォルトが "decode with locale.getpreferredencoding(False)
" から "do not decode, and return raw " のbytes
代わりにraw に変更されることを意味するためですstr
。繰り返しますが、ドキュメントから:
テキスト モードでは、エンコーディングが指定されていない場合、使用されるエンコーディングはプラットフォームに依存します。現在のロケール エンコーディングを取得するために locale.getpreferredencoding(False) が呼び出されます。(未加工のバイトの読み取りと書き込みには、バイナリ モードを使用し、エンコーディングは未指定のままにします。)
でも:
'encoding' … テキスト モードでのみ使用する必要があります。
そして、少なくとも 3.3 では、これが強制されています。バイナリモードで試してみると、ValueError: binary mode doesn't take an encoding argument
.
では、2.x と 3.x の両方で動作するコードを書きたい場合は、何を使用すればよいでしょうか? を扱いたい場合はbytes
、明らかf
に f1 are the same. But if you want to deal in
str , as appropriate for each version, the simplest answer is to write different code for each, probably
f and
f2` とそれぞれ。これが頻繁に発生する場合は、いずれかのラッパー関数を作成することを検討してください。
if sys.version_info >= (3, 0):
def crlf_open(path, mode):
return open(path, mode, newline='')
else:
def crlf_open(path, mode):
return open(path, mode+'b')
マルチバージョン コードを記述する際に注意すべきもう 1 つの点は、ロケールを認識したコードを記述していない場合、locale.getpreferredencoding(False)
ほとんどの場合 3.x では適切な値が返されるが、通常'US-ASCII'
は 2.xでは返されるだけであるということです。を使用するlocale.getpreferredencoding(True)
のは技術的には正しくありませんが、エンコーディングについて考えたくない場合は、実際に使用する可能性が高くなります。(2.x と 3.x のインタープリターで両方の方法で呼び出してみて、理由を確認するか、ドキュメントを読んでください。)
もちろん、ファイルのエンコーディングを実際に知っている場合は、とにかく推測するよりも常に優れています。
いずれの場合も、'r'
は「読み取り専用」を意味します。モードを指定しない場合、デフォルトは'r'
であるため、デフォルトに相当するバイナリモードは です'rb'
。
バイナリ モードでファイルを開く必要があります。
f = open('data.txt', 'rb')
data = f.read()
( 'r'
「読み取り」の場合'b'
、「バイナリ」の場合)
その後、すべてがそのまま返され、何も正規化されません
で「バイナリの読み取り」を要求するだけopen
です:
f = open('data.txt', 'rb')
data = f.read()
を使用してファイルを開きますopen('data.txt', 'rb')
。ドキュメントを参照してください。