web-dev-qa-db-ja.com

Pythonでファイルを開くには、try / catchよりも「with」の方が優れていますか?

withステートメントを使用すると、これを有効にすることができます。

try:
    f = open(my_file)
    do_stuff_that_fails()
except:
    pass
finally:
    f.close()

に:

with open(my_file) as f:
    do_stuff_that_fails()

しかし、それはどのように優れていますか?ファイルを開くことができないというケースを処理する必要があります(ユーザーに許可がないことを伝えるようユーザーに求めるなど)。したがって、実際には次のようになります。

try:
    with open(my_file) as f:
        do_stuff_that_fails()
except (IOError, OSError, Failure) as e:
    do_stuff_when_it_doesnt_work()

次と同等です:

try:
    f = open(my_file)
    do_stuff_that_fails()
except (IOError, OSError, Faillure) as e:
    do_stuff_when_it_doesnt_work()
finally:
    f.close()

はい、2行取得しましたが、読みやすくしないネストレベルを追加しました。 withステートメントの目的は2行を節約することですか、それとも何か不足していますか?

そのためだけにキーワードを追加するのはたくさんあるように思えるので、追加のtry/exceptを処理するための構文があるのではないかと思います。

40
e-satis

あなたが与える例では、notより良いです。同じタイプの無関係な例外をキャッチしないように、例外をスローされるポイントの近くでキャッチすることをお勧めします。

try:
    file = open(...)
except OpenErrors...:
    # handle open exceptions
else:
    try:
        # do stuff with file
    finally:
        file.close()

残念ながらこれは冗長ですが、 withステートメント では、評価中にスローされた例外をキャッチできません。 提案 があり、メーリングリストでこの効果に例外処理を追加しました:

with open(...) as file:
    # do stuff with file
except OpenErrors...:
    # handle open exceptions

しかし、これは ショットダウン でした。

最後に、コンテキストマネージャーを次のように直接入力および終了できることに注意してください。

file = open(...).__enter__()
file.__exit__(typ, val, tb)

これについて詳しく説明します here および here

一般的なガイドラインとして、withステートメントは、例外が予期されない場合に最適であり、デフォルトの「enter/open/acquire」動作が適切です。例には、必要なファイル、および単純なロックが含まれます。

16
Matt Joiner

それはresource managementのためです...そうでなければ例外にどう反応するかではありません:)

withを使用する場合、f.close()を「忘れる」方法はありません。この方法では、C#のusingと同じ役割を果たします。

ハッピーコーディング。

7
user166390