web-dev-qa-db-ja.com

try-exceptブロックでpython "with"ステートメントを使用する

これはpython "with"ステートメントをtry-exceptブロックと組み合わせて使用​​する正しい方法ですか?:

try:
    with open("file", "r") as f:
        line = f.readline()
except IOError:
    <whatever>

そうであれば、古いやり方を検討してください:

try:
    f = open("file", "r")
    line = f.readline()
except IOError:
    <whatever>
finally:
    f.close()

ここで「with」ステートメントの主な利点は、3行のコードを削除できることですか?私にとって魅力的ではないようですこのユースケースの場合(「with」ステートメントには他の用途があることは理解していますが)。

編集:上記の2つのコードブロックの機能は同じですか?

EDIT2:最初のいくつかの答えは、「with」を使用する利点について一般的に説明していますが、ここではわずかな利点のようです。私たちは皆、何年もの間f.close()を明示的に呼び出してきました(またはすべきでした)。利点の1つは、ずさんなコーダーが「with」を使用することで恩恵を受けることです。

86
gaefan
  1. 指定した2つのコードブロックは、notと同等です
  2. 古いやり方で記述したコードには重大なバグがあります:ファイルを開くことができない場合、finally句で2番目の例外が発生しますfはバインドされていません。

同等の古いスタイルのコードは次のとおりです。

try:
    f = open("file", "r")
    try:
        line = f.readline()
    finally:
        f.close()
except IOError:
    <whatever>

ご覧のとおり、withステートメントを使用すると、エラーが発生しにくくなります。 Python(2.7、3.1)の新しいバージョンでは、1つのwithステートメントで複数の式を組み合わせることもできます。例:

with open("input", "r") as inp, open("output", "w") as out:
    out.write(inp.read())

それに加えて、私は個人的に、できるだけ早く例外をキャッチするのは悪い習慣だと考えています。これは例外の目的ではありません。失敗する可能性があるIO関数がより複雑な操作の一部である場合、ほとんどの場合、IOErrorは操作全体を中止するため、外部レベルで処理されます。withステートメントを使用すると、これらすべてを取り除くtry...finallyステートメントは内部レベルにあります。

126
Bernd Petersohn

finallyブロックの内容が、開かれているファイルオブジェクトのプロパティによって決定される場合、ファイルオブジェクトの実装者がfinallyブロックを書き込むのはなぜではないのですか? それがwithステートメントの利点。この特定のインスタンスで3行のコードを保存するよりもはるかに優れています。

そして、はい、withtry-exceptを組み合わせた方法は、それを行う唯一の方法です。openステートメント自体で発生した例外エラーは、 withブロック。

6
Peter Milley

行を減らすだけだという「with」ステートメントについて間違っていると思います。実際に初期化を行い、分解を処理します。

あなたの場合、「と」は

  • ファイルを開く、
  • その内容を処理し、
  • 必ず閉じてください。

「with」ステートメントを理解するためのリンクは次のとおりです。 http://effbot.org/zone/python-with-statement.htm

編集:はい、 "with"の使用法は正しく、両方のコードブロックの機能は同じです。 「with」を使用する理由についての質問それはあなたがそれで得られる利点のためです。誤ってf.close()が見つからないことについて言及したように。

1
YoK