web-dev-qa-db-ja.com

python try:except:finally

# Open new file to write
file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    file.write("Hello World!")
    file.close()

上記のコードは関数からリッピングされています。ユーザーのシステムの1つが次のエラーを報告しています:

file.write("Hello World!")

エラー:

AttributeError: 'NoneType' object has no attribute 'write'

質問は、pythonが特定のファイルを開くのに失敗した場合、「except」ブロックが実行されて戻る必要がありますが、特定のエラーをスローしている行に制御が移ります。ファイル」変数は「なし」です。

ポインタはありますか?

44
user354051

finallyブロック内のファイルに書き込むべきではありません。そこで発生した例外はexceptブロックによってキャッチされないためです。

Tryブロックによって発生した例外がある場合、exceptブロックが実行されます。 finallyブロックalwaysは、何でも起こります。

また、file変数をnoneに初期化する必要はありません。

returnブロックでexceptを使用しても、finallyブロックはスキップされません。その性質上、スキップすることはできません。そのため、「クリーンアップ」コードをそこに配置する(つまり、ファイルを閉じる)必要があります。

したがって、try:except:finallyを使用する場合は、次のようにする必要があります。

try:
    f = open("file", "w")
    try:
        f.write('Hello World!')
    finally:
        f.close()
except IOError:
    print 'oops!'

これを行うもっときれいな方法は、withステートメントを使用することです。

try:
    with open("output", "w") as outfile:
        outfile.write('Hello World')
except IOError:
    print 'oops!'
97
Acorn

ファイルが開かれていない場合、file = open(filePath, 'w')行は失敗するため、fileには何も割り当てられません。

次に、except句が実行されますが、ファイルには何もないため、file.close()は失敗します。

例外が発生した場合でも、finally句は常に実行されます。 fileはまだNoneなので、別の例外が発生します。

例外がなかった場合にのみ発生することに対して、elseの代わりにfinally句が必要です。

    try:
        file = open(filePath, 'w')
    except IOError:
        msg = "Unable to create file on disk."
        return
    else:
        file.write("Hello World!")
        file.close()

なぜelseですか? Pythonドキュメント say:

Else節の使用は、try節にコードを追加するよりも優れています。try... exceptステートメントで保護されているコードによって発生した例外を誤ってキャッチすることを避けるためです。

つまり、これはIOErrorまたはwrite呼び出しからcloseをキャッチしません。その理由は、「ディスク上にファイルを作成できません」という理由がなかったからです。これは、コードが準備されていない別のエラーだったでしょう。このようなエラーを処理しようとしないことをお勧めします。

27
Petr Viktorin

を含むロジックは何ですか

file.write("Hello World!")

finally句内?? try句自体に配置する必要があると思います。

try:
        file = open(filePath, 'w')
        file.write("Hello World!")
except IOError:
        print("Unable to create file on disk.")
finally:
        file.close()
4
Sreenath Nannat

これが問題に対する最も直接的な解決策です。 finallyブロックでfile_obj != Noneをチェックするイディオムを使用します。

ところで、fileはPythonクラス名であるため、別の変数名を選択する必要があります。

file = None
try:
    file = open(filePath, 'w')
except IOError:
    msg = ("Unable to create file on disk.")
    file.close()
    return
finally:
    if file != None:
        file.write("Hello World!")
        file.close()

(タイプがIOErrorであるため)実行しないことを除いて、file = Noneであるため、AttributeErrorタイプの別のエラーをスローする最後の部分です。

1
TigOldBitties

次のようなことができます:

try:
    do_some_stuff()
finally:
    cleanup_stuff()
1
user5578789

例外が発生した場合でも、最終的には常に「end」で呼び出されます。これを使用して、開いているリソース(DB接続、ファイルなど)が閉じられていることを確認できます。

セマンティクスを誤解したと思います。

ロジックは「try」内にある必要があり、「except」ブロック内の例外を処理する必要があり、メソッドがどのように終了しても「finally」が実行されるため、それを使用してクリーンアップします。

0
pcalcao