Pythonの「with」ステートメントをtry-exceptブロックで使用する


96

これは、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」を使用することから利益を得るということです。



私にとって、finallyステートメントでclose()のことを覚えておく必要がないことは、「with」を使用する十分な理由です。多くのコードがリソースを閉じられないのを見てきました。そして、私が見る限り、「with」には欠点はありません。
ラウル・サリナス- Monteagudo

回答:


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

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

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内部レベルでこれらすべてのステートメントを取り除くことができます。


7

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

そして、そう、あなたが組み合わされてきた方法withとは、try-except内部に発生する例外エラーとして、かなりそれを行うための唯一の方法であるopen文自体が内部にキャッチすることができないwithブロック。


1

"with"ステートメントは行数を減らすだけだと間違っていたと思います。実際に初期化を行い、ティアダウンを処理します。

あなたの場合「と」は

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

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

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


-4

次のコードのよりPython的な方法は次のとおりです。

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

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

1
コードのフォーマットを追加しました。読みやすくなります。しかし、私がインデントを壊していないことを確認するためにダブルチェックすることもできます。
andrewsi

2
いいえ、あなたのバージョンは元のコードと同じことをしません。欠落しているreadline()呼び出しを追加しても、readline()結果がである場合、バージョンはファイルを閉じませんIOError
Aleksi Torhamo 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.