web-dev-qa-db-ja.com

ipythonで開いているすべてのファイルを閉じます

Ipythonを使用しているときに、書き込みモードでファイルを開いた関数で例外が発生する場合があります。これは、次に関数を実行したときに値エラーが発生することを意味します。

ValueError:ファイル 'filename'はすでに開かれています。書き込みモードで再度開く前に閉じてください。

ただし、関数がバグアウトされたため、(関数内で作成された)ファイルハンドルが失われ、閉じることができません。それを回避する唯一の方法は、ipythonセッションを閉じることであるように思われます。その時点で、次のメッセージが表示されます。

残りの開いているファイルを閉じる:ファイル名...完了

セッションを終了せずにファイルを閉じるようにipythonに指示する方法はありますか?

12
tdc

ファイルを操作するときは、常にwithステートメントを使用するようにしてください。たとえば、次のようなものを使用します

with open("x.txt") as fh:
    ...do something with the file handle fh

これにより、withブロックの実行中に問題が発生し、例外が発生した場合に、ファイルが閉じられることが保証されます。詳細については、 ドキュメント付き を参照してください。

編集:コメントでの議論に続いて、OPは同時に多数のファイルを開く必要があり、からのデータを使用する必要があるようです一度に複数のファイル。明らかに、開かれるファイルごとに1つずつ、ネストされたwithステートメントがたくさんあることはオプションではなく、「フラットはネストよりも優れている」という理想に反します。

1つのオプションは、計算をtry/finallyブロックでラップすることです。例えば

file_handles = []
try:
    for file in file_list:
        file_handles.append(open(file))

    # Do some calculations with open files

finally:
    for fh in file_handles:
        fh.close()

Finalブロックには、例外が発生した場合でも、tryexcept、またはelseブロックの後に実行する必要があるコードが含まれています。 ドキュメント から:

finallyが存在する場合は、「クリーンアップ」ハンドラーを指定します。 try句とexcept句を含むelse句が実行されます。いずれかの句で例外が発生して処理されない場合、例外は一時的に保存されます。 finally句が実行されます。保存された例外がある場合は、finally句の最後で再発生します。 finally句で別の例外が発生したり、returnステートメントまたはbreakステートメントを実行したりすると、保存された例外は失われます。 finally句の実行中は、プログラムは例外情報を利用できません。

11
Chris

いくつかのアイデア:

  • ファイルを操作するときは常にfinally(またはwithブロック)を使用して、ファイルが適切に閉じられるようにします。
  • os.close(n)を使用して、非標準のファイル記述子を盲目的に閉じることができます。ここで、nは2より大きい数値です(これはUNIX固有であるため、/proc/ipython_pid/fd/を覗いてみてください。プロセスがこれまでに開いた記述子)。
  • キャプチャされたスタックフレームのローカルを調べて、わがままなファイルへの参照を見つけて閉じることができるかどうかを確認できます... sys.last_tracebackを見てください
7
fortran