web-dev-qa-db-ja.com

rモードとrbモードでのテキストファイルの解析の違い

「r」モードでのテキストファイルの解析が「rb」モードでの解析よりも便利なのはなぜですか?特に、問題のテキストファイルに非ASCII文字が含まれている可能性がある場合。

52

これは、使用しているPythonのバージョン。InPython 2、 Chris Drappier's answer が適用されます。

Python 3、その異なる(より一貫した)ストーリー:テキストモード(_'r'_)では、Pythonは、あなたがそれを与えるテキストエンコーディング(または、もしあなたが与えないなら、プラットフォーム依存のデフォルト)、そしてread()はあなたにstrを与えます。バイナリ(_'rb'_)モード、Pythonは、ファイルが文字として合理的に解析できるものを含むとは想定していません。また、read()bytesオブジェクトを提供します。

また、Python 3)では、ユニバーサルモードの改行(_'\n'_とプラットフォーム固有の改行規則を変換するので、気にする必要はありません)はテキストモードで使用できますWindowsだけでなく、anyプラットフォーム上のファイル。

60
lvc

ドキュメント から:

Windowsでは、モードに「b」を追加すると、ファイルがバイナリモードで開かれるため、「rb」、「wb」、「r + b」などのモードもあります。 Pythonは、テキストファイルとバイナリファイルを区別します。テキストファイルの行末文字は、データの読み取りまたは書き込み時に自動的にわずかに変更されます。 ASCIIテキストファイルのファイルデータは問題ありませんが、JPEGまたはEXEファイルのようなバイナリデータは破損します。このようなファイルを読み書きするときは、バイナリモードを使用するように注意してください。モードに「b」を追加しても問題ないため、すべてのバイナリファイルに対してプラットフォームに依存せずに使用できます。

22
Chris Drappier

違いは、行末(EOL)の処理方法にあります。異なるオペレーティングシステムは異なる文字を使用してEOLをマークします-Unixでは\n、OS Xより前のMacバージョンでは\r、Windowsでは\r\n。ファイルがテキストモードで開かれ、ファイルが読み取られると、Pythonはファイルから読み取られたOS固有の行末文字を\nに置き換えます。逆も同様です。つまり、テキストモードで開いたファイルに\nを書き込もうとすると、OS固有のEOL文字が書き込まれますos.linesepをチェックすると、OSのデフォルトのEOLを見つけることができます。

ファイルをバイナリモードで開くと、マッピングは行われません。あなたが読むものはあなたが得るものです。テキストモードがデフォルトモードであることに注意してください。そのため、非テキストファイル(画像、動画など)を処理する場合は、必ずバイナリモードでファイルを開いてください。そうしないと、バイトを導入(または削除)してファイルを混乱させることになります。

Pythonには、ユニバーサル改行モードもあります。このモードでファイルを開くと、Pythonはすべての文字\r\nおよび\r\n\nにマッピングします。

12
shining

明確化と回答のために Agostinoのコメント/質問 (コメントするのに十分な評判がありませんので、これを回答として記載してください...):

Python 2、テキストモードでもバイナリモードでも行末の変更は行われません-前述のように、Python 2 Chris Drappier's answer が適用されます(最近のリンクは3.x Python docsを指しますが、Chrisの引用テキストはもちろん Python 2の入出力チュートリアル =)

いいえ、nottextモードでファイルを開くことは本当ですwith Python 2Windows以外は行末の変更を行います:

0 $ cat data.txt 
line1
line2
line3
0 $ file data.txt 
data.txt: ASCII text, with CRLF line terminators
0 $ python2.7 -c 'f = open("data.txt"); print f.readlines()'
['line1\r\n', 'line2\r\n', 'line3\r\n']
0 $ python2.7 -c 'f = open("data.txt", "r"); print f.readlines()'
['line1\r\n', 'line2\r\n', 'line3\r\n']
0 $ python2.7 -c 'f = open("data.txt", "rb"); print f.readlines()'

ただし、Python 2でユニバーサル改行モードでファイルを開くことは可能です。

0 $ python2.7 -c 'f = open("data.txt", "rU"); print f.readlines()'
['line1\n', 'line2\n', 'line3\n']

(ユニバーサル改行モード指定子は、Python 3.x)で非推奨になりました)

Python 3、一方で、プラットフォーム固有の行末は、テキストモードでファイルを読み取るときに '\ n'に正規化され、 '\ n'は現在のプラットフォームに変換されますテキストモードでの書き込み時のデフォルトの行末(テキストモードでのbytes <-> unicode <-> bytesデコード/エンコードに加えて)たとえば、LinuxでDos/Win CRLF行終了ファイルを読み取ると、行が正規化されます「\ n」で終わります。

2
Holger Joukl