1. ホーム
  2. python

[解決済み] Pythonのwith文とtry-exceptブロックの使い分け

2022-10-27 23:51:57

質問

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" ステートメントが他の用途を持っていることを理解していますが)。

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

EDIT2: 最初のいくつかの回答は、一般的に "with" を使用する利点について話していますが、それらはここではわずかな利点のようです。 私たちは皆、何年もの間、明示的に f.close() を呼び出してきました (または、そうすべきでした)。 私は、1 つの利点は、ずさんなコーダーが "with" を使用することで利益を得ることだと思います。

どのように解決するのですか?

  1. あなたが与えた2つのコードブロックは ではなく と同じです。
  2. として記述したコードは 古い方法 のようなものです。 には重大なバグがあります。 ファイルを開くのに失敗した場合 で二度目の例外が発生します。 finally 節で二番目の例外が発生します。 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 ステートメントを取り除くことができます。