web-dev-qa-db-ja.com

それらへの参照を持たないファイルを閉じる必要がありますか?

プログラミングの完全な初心者として、ファイルを開いたり閉じたりする基本的な概念を理解しようとしています。私がしている1つの演習は、あるファイルから別のファイルに内容をコピーできるスクリプトを作成することです。

in_file = open(from_file)
indata = in_file.read()

out_file = open(to_file, 'w')
out_file.write(indata)

out_file.close()
in_file.close()

私はこのコードを短くしようとして、これを思いつきました:

indata = open(from_file).read()
open(to_file, 'w').write(indata)

これは機能し、私にはもう少し効率的に見えます。しかし、これは私が混乱する場所でもあります。開いているファイルへの参照は省略したと思います。 in_file変数とout_file変数は必要ありませんでした。ただし、これにより2つのファイルが開いたままになりますが、それらを参照するファイルはありませんか?これらを閉じるには、どうすればよいですか?

このトピックに光を当てる助けは大歓迎です。

52
Roy Crielaard

これに対処するPython的な方法は、 withコンテキストマネージャー を使用することです。

_with open(from_file) as in_file, open(to_file, 'w') as out_file:
    indata = in_file.read()
    out_file.write(indata)
_

このようなファイルで使用すると、withは、read()またはwrite()がエラーをスローした場合でも、必要なすべてのクリーンアップが確実に行われます。

57
RoadieRich

デフォルトのpython interpeter、CPython、参照カウントを使用します。つまり、オブジェクトへの参照がなくなると、ガベージコレクションが行われます。つまり、クリーンアップされます。

あなたの場合、やって

open(to_file, 'w').write(indata)

to_fileのファイルオブジェクトを作成しますが、名前に割り当てません-これは、それへの参照がないことを意味します。この行の後にオブジェクトを操作することはできません。

CPythonはこれを検出し、使用後にオブジェクトをクリーンアップします。ファイルの場合、これは自動的に閉じることを意味します。原則として、これは問題なく、プログラムはメモリをリークしません。

「問題」は、このメカニズムがCPythonインタープリターの実装の詳細であることです。言語標準explicitlyはそれを保証しません! pypyなどの代替インタープリターを使用している場合、ファイルの自動クローズが遅延する場合があります無期限。これには、終了時に書き込みをフラッシュするなどの他の暗黙的なアクションが含まれます。

この問題は、他のリソースにも適用されます。ネットワークソケット。 alwaysこのような外部リソースを明示的に処理することをお勧めします。 python 2.6なので、withステートメントはこれをエレガントにします:

with open(to_file, 'w') as out_file:
    out_file.write(in_data)

TLDR:動作しますが、実行しないでください。

36
MisterMiyagi

ファイルオブジェクトを処理する場合は、withキーワードを使用することをお勧めします。これには、途中で例外が発生した場合でも、スイートの終了後にファイルが適切に閉じられるという利点があります。また、同等のtry-finallyブロックを記述するよりもはるかに短くなります。

>>> with open('workfile', 'r') as f:
...     read_data = f.read()
>>> f.closed
True
7
python

これまでの答えは絶対に正しいですpythonで作業する場合with open()コンテキストマネージャーを使用する必要があります。これは優れた組み込み機能であり、一般的なプログラミングタスク(ファイルの開閉)のショートカットに役立ちます。

ただし、あなたは初心者であり、キャリア全体で コンテキストマネージャ および 自動参照カウント にアクセスできないため、-からの質問に対処します一般的なプログラミングスタンス。

コードの最初のバージョンはまったく問題ありません。ファイルを開き、参照を保存し、ファイルから読み取り、閉じます。これは、言語がタスクのショートカットを提供しない場合に多くのコードが記述される方法です。私が改善する唯一のことは、close()をファイルを開いて読み込む場所に移動することです。ファイルを開いて読み取ると、内容がメモリに保存され、ファイルを開く必要がなくなります。

in_file = open(from_file)
indata = in_file.read()
out_file.close() 

out_file = open(to_file, 'w')
out_file.write(indata)
in_file.close()
7
Darrick Herwehe

ファイルを閉じなかったことを心配せずにファイルを開く安全な方法は次のとおりです。

with open(from_file, 'r') as in_file:
    in_data = in_file.read()

with open(to_file, 'w') as out_file:
    outfile.write(in_data)
5
Mark Skelton