[解決済み] Pythonでファイルを一行ずつ読むにはどうしたらいいですか?
質問
前時代(Python 1.4)では、そうでした。
fp = open('filename.txt')
while 1:
line = fp.readline()
if not line:
break
print line
Python 2.1以降では、そうしました。
for line in open('filename.txt').xreadlines():
print line
は、Python 2.3 で便利なイテレータプロトコルを手に入れ、できるようになる前のものです。
for line in open('filename.txt'):
print line
より冗長なものを使っている例も見かけます。
with open('filename.txt') as fp:
for line in fp:
print line
は、今後この方法が望ましいのでしょうか?
[編集] withステートメントがファイルのクローズを保証することはわかりますが、なぜファイルオブジェクトのためのイテレータプロトコルにそれが含まれていないのでしょうか?
どのように解決するのですか?
以下のようにすると良いという理由は、まさに一つです。
with open('filename.txt') as fp:
for line in fp:
print line
私たちは皆、CPythonのガベージコレクションのための比較的決定論的な参照カウントのスキームに甘えています。 他の、仮想的な Python の実装は、必ずしも "enough" がなければファイルを閉じないでしょう。
with
ブロックがない場合、メモリを再利用するために他のスキームを使用した場合、必ずしも十分に速くファイルを閉じるとは限りません。
このような実装では、ガベージコレクタが孤立したファイルハンドルのファイナライザを呼び出すよりも速く、コードがファイルを開くと、OS から "too many files open" エラーを受け取ることがあります。 通常の回避策は、GC を直ちに起動することですが、これは厄介なハックで ごとに 関数で実行しなければなりません。 なんという悪夢でしょう。
あるいは、単に
with
ブロックを使うこともできます。
ボーナス質問
(質問の客観的な側面にのみ興味がある場合は、今読むのをやめてください)。
なぜそれがファイルオブジェクトのイテレータプロトコルに含まれていないのでしょうか?
これはAPI設計に関する主観的な質問なので、2つに分けて主観的な回答をしています。
直感的なレベルでは、これは間違っていると感じます。なぜなら、イテレータプロトコルは2つの別々のことをすることになるからです-行の上の反復処理 と そして、単純に見える関数に 2 つのアクションをさせることは、しばしば悪い考えです。 この場合、イテレータはファイルのコンテンツに準機能的な値ベースの方法で関係しますが、ファイルハンドルの管理は完全に別のタスクであるため、特に悪く感じられます。 両方を目に見えないように 1 つのアクションに押し込むことは、コードを読む人間にとって驚きであり、プログラムの動作について推論することをより困難にします。
他の言語も基本的には同じ結論に達しています。 Haskell は一時期、いわゆる "lazy IO" と呼ばれる、ファイルを繰り返し処理し、ストリームの最後に到達すると自動的にクローズさせることができるものに浮気しましたが、最近では Haskell で lazy IO を使うことはほぼ一般的に推奨されておらず、Haskell ユーザーはほとんど Conduit などのより明確なリソース管理へと移行しています。
with
ブロックのように動作します。
技術的なレベルでは、Pythonでファイルハンドルを使って行いたいことがいくつかありますが、もし反復処理がファイルハンドルを閉じてしまうと、うまく動作しないでしょう。 たとえば、私がファイルに対して2回反復処理を行う必要があるとします。
with open('filename.txt') as fp:
for line in fp:
...
fp.seek(0)
for line in fp:
...
これはあまり一般的ではない使用例ですが、もともと上の3行があった既存のコードベースに、下の3行のコードを追加しただけかもしれないという事実を考えてみてください。 もしイテレーションでファイルが閉じられてしまったら、そんなことはできません。 ですから、反復処理とリソース管理を別々にすることで、コードの塊をより大きな、動作するPythonプログラムに構成することがより簡単になるのです。
コンポーザビリティは言語やAPIの最も重要なユーザビリティの特徴の1つです。
関連
-
PythonによるLeNetネットワークモデルの学習と予測
-
Python 可視化 big_screen ライブラリ サンプル 詳細
-
[解決済み】なぜ「LinAlgError: Grangercausalitytestsから「Singular matrix」と表示されるのはなぜですか?
-
[解決済み】TypeError: 系列を <class 'float'> に変換することができません。
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] ファイルのコピー方法について教えてください。
-
[解決済み] Pythonでファイルやフォルダを削除する方法は?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み】2つの辞書を1つの式でマージする(辞書の和をとる)には?)
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonの非常に便利な2つのデコレーターを解説
-
python string splicing.join()とsplitting.split()の説明
-
Python機械学習Githubが8.9Kstarsに達したモデルインタープリタLIME
-
pyCaret効率化乗算器 オープンソース ローコード Python機械学習ツール
-
Python Pillow Image.save jpg画像圧縮問題
-
[解決済み】RuntimeWarning: invalid value encountered in double_scalars で numpy の除算ができない。
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み] builtins.TypeError: strでなければならない、bytesではない
-
[解決済み】Python: OverflowError: 数学の範囲エラー
-
[解決済み】 TypeError: += でサポートされていないオペランド型: 'int' および 'list' です。