428

なぜステートメントが必要なfinallyのかわかりません。try...except...finally私の意見では、このコードブロック

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

を使用してこれと同じfinallyです:

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

私は何かが足りないのですか?

4

17 に答える 17

567

あなたが早く戻った場合、それは違いを生みます:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

これと比較してください:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

違いを引き起こす可能性のあるその他の状況:

  • 例外がexceptブロック内でスローされた場合。
  • 例外がスローされrun_code1()たが、それがではない場合TypeError
  • continueおよびステートメントなどの他の制御フローbreakステートメント。
于 2012-07-18T23:46:02.240 に答える
122

例外をキャッチしなくてもfinally、例外が発生したかどうかに関係なく、ファイルまたはリソースが閉じられているか解放されていることを確認するために使用できます。(または、その特定の例外をキャッチしない場合。)

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

この例では、withステートメントを使用する方がよいでしょうが、この種の構造は他の種類のリソースに使用できます。

数年後、私は読者が面白いと思うかもしれない虐待についてのブログ投稿を書きました。finally

于 2012-07-18T23:51:20.630 に答える
32

それらは同等ではありません。finallyコードは他に何が起こっても実行されます*。実行する必要のあるクリーンアップコードに役立ちます。


*Mark Byersがコメントしたように、プロセスがすぐに終了する原因となるものは、finally-codeの実行も妨げます。後者はos._exit().またはパワーカットである可能性がありますが、無限ループまたはその他のものもそのカテゴリに分類されます。

于 2012-07-18T23:46:12.380 に答える
27

上記の他の回答に追加するために、finally句は何があっても実行されますが、else句は例外が発生しなかった場合にのみ実行されます。

たとえば、例外なくファイルに書き込むと、次のように出力されます。

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

出力:

Writing to file.
Write successful.
File closed.

例外がある場合、コードは次のように出力します(ファイルを読み取り専用に保つことにより、意図的なエラーが発生することに注意してください。

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

出力:

Could not write to file.
File closed.

finally例外に関係なく句が実行されることがわかります。お役に立てれば。

于 2017-12-13T06:46:06.257 に答える
11

ドキュメントで説明されているように、この句は、すべての状況finallyで実行する必要のあるクリーンアップアクションを定義することを目的としています。

が存在する場合finallyは、「クリーンアップ」ハンドラーを指定します。try anyexceptおよび句を含む句が実行されますelse。いずれかの句で例外が発生し、処理されない場合、例外は一時的に保存されます。finally句が実行されます。保存された例外がある場合は、finally 句の最後で再発生します。

例:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print("division by zero!")
...     else:
...         print("result is", result)
...     finally:
...         print("executing finally clause")
...
>>> divide(2, 1)
result is 2.0
executing finally clause
>>> divide(2, 0)
division by zero!
executing finally clause
>>> divide("2", "1")
executing finally clause
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in divide
TypeError: unsupported operand type(s) for /: 'str' and 'str'

ご覧のとおり、このfinally句はどのような場合でも実行されます。2つのTypeError文字列を分割することによって発生したものは、句によって処理されないため、句が実行されexceptた後に再発生します。finally

実際のアプリケーションでは、finally句は、リソースの使用が成功したかどうかに関係なく、外部リソース(ファイルやネットワーク接続など)を解放するのに役立ちます。

于 2017-12-03T13:20:56.213 に答える
8

コードブロックは同等ではありません。このfinally句はrun_code1()、、以外の例外をスローしたTypeError場合、またはrun_code2()例外をスローしたother_code()場合にも実行されますが、最初のバージョンではこれらの場合は実行されません。

于 2012-07-18T23:46:36.663 に答える
7

最初の例でrun_code1()は、そうでない例外が発生した場合はどうなりTypeErrorますか?...other_code()実行されません。

finally:これをバージョンと比較してくださいother_code()。例外が発生した場合でも、実行されることが保証されています。

于 2012-07-18T23:47:41.467 に答える
7

違いを明確にするためのコードを次に示します。

...

try: 
  a/b
  print('In try block')
  
except TypeError:
  print('In except block')
  
finally: 
  print('In finally block')

print('Outside')

a, b = 0, 1

出力:

In try block 
In finally block 
Outside

(ブロックがスキップされることを除いて、エラーはありません。)


a, b = 1, 0

出力:

In finally block

Traceback (most recent call last):
a/b
ZeroDivisionError: division by zero

(ZeroDivisionErrorには例外処理は指定されておらず、finallyブロックのみが実行されます。


a, b = 0, '1'

出力:

In except block 
In finally block 
Outside

(例外は適切に処理され、プログラムは中断されません。)


注:すべてのタイプのエラーを処理するためのexceptブロックがある場合、 finallyブロックは不要になります。

于 2021-08-09T10:05:10.800 に答える
5

デルファイを専門的に数年間使用することで、最終的に使用するクリーンアップルーチンを保護する方法を学びました。Delphiは、メモリリークを引き起こさないように、tryブロックの前に作成されたリソースをクリーンアップするためにfinallyの使用をほぼ強制します。これは、Java、Python、Rubyの仕組みでもあります。

resource = create_resource
try:
  use resource
finally:
  resource.cleanup

そして、tryとfinallyの間に何をするかに関係なく、リソースはクリーンアップされます。また、実行がtryブロックに到達しない場合、クリーンアップされません。(つまりcreate_resource、それ自体が例外をスローします)それはあなたのコードを「例外安全」にします。

なぜ実際にfinallyブロックが必要なのかについては、すべての言語で必要なわけではありません。C ++では、例外がスタックを展開したときにクリーンアップを強制するデストラクタを自動的に呼び出しました。これは、試行する...最終的に言語と比較して、よりクリーンなコードの方向へのステップアップだと思います。

{    
  type object1;
  smart_pointer<type> object1(new type());
} // destructors are automagically called here in LIFO order so no finally required.
于 2018-03-16T06:12:18.040 に答える
4

最後に、メインの作業のコードを実行する前に「オプションの」コードを実行する場合や、さまざまな理由でオプションのコードが失敗する可能性がある場合にも使用できます。

store_some_debug_info次の例では、どのような種類の例外がスローされるかは正確にはわかりません。

実行できます:

try:
  store_some_debug_info()
except Exception:
  pass
do_something_really_important() 

しかし、ほとんどのリンターは、あまりにも漠然とした例外を捕まえることについて不平を言うでしょう。passまた、エラーのみを選択しているため、exceptブロックは実際には価値を追加しません。

try:
  store_some_debug_info()
finally:
  do_something_really_important()     

上記のコードは、コードの最初のブロックと同じ効果がありますが、より簡潔です。

于 2017-02-17T17:14:46.730 に答える
3

finally「クリーンアップアクション」を定義するためのものです。句は、例外が発生したかどうかに関係なくfinally、ステートメントを終了する前に任意のイベントで実行されます。try

@Byersの例を2番目に示します。

于 2015-05-15T17:59:29.023 に答える
3

完璧な例は次のとおりです。

try:
    #x = Hello + 20
    x = 10 + 20 
except:
    print 'I am in except block'
    x = 20 + 30
else:
    print 'I am in else block'
    x += 1
finally:
    print 'Finally x = %s' %(x)
于 2017-10-02T06:33:36.210 に答える
3

tryブロックには、tryステートメントという1つの必須句があります。例外、else、finally句はオプションであり、ユーザーの好みに基づいています。

finally:Pythonは、tryステートメントを離れる前に、プログラムを終了している場合でも、任意の条件下でfinallyブロックのコードを実行します。たとえば、exceptまたはelseブロックでコードを実行しているときにPythonでエラーが発生した場合でも、プログラムを停止する前にfinallyブロックが実行されます。

于 2018-10-07T04:10:27.783 に答える
3

このコードをfinallyブロックなしで最初に実行してみてください。

1 / 0ゼロ除算エラーが発生します。

    try:
        1 / 0    
        print(1)
        
    except Exception as e:
        1 / 0
        print(e)
        

次に、このコードを実行してみてください。

    try:
        1 / 0    
        print(1)
        
    except Exception as e:
        1 / 0
        print(e)
   
    finally:
        print('finally')

最初のケースではfinallyブロックがないため
、exceptブロックでエラーが発生すると、プログラムの実行が停止し、exceptブロックの後に何も実行できなくなります。

ただし、2番目のケースでは、
エラーが発生しますが、プログラムが停止する前に、Pythonは最初にfinallyブロックを実行してから、プログラムを停止させます。
それが、あなたが最終的に使用し、本当に重要なことをする理由です。

于 2021-03-09T17:13:02.100 に答える
2

これらのPython3コードを実行して、最終的に必要なものを監視します。

ケース1:

count = 0
while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")
        finally:
            print("Your Attempts: {}".format(count))

ケース2:

count = 0

while True:
    count += 1
    if count > 3:
        break
    else:
        try:
            x = int(input("Enter your lock number here: "))

            if x == 586:
                print("Your lock has unlocked :)")

                break
            else:
                print("Try again!!")

                continue

        except:
            print("Invalid entry!!")

        print("Your Attempts: {}".format(count))

毎回次の入力を試してください。

  1. ランダムな整数
  2. 586である正しいコード(これを試してみてください、そしてあなたはあなたの答えを得るでしょう)
  3. ランダムな文字列

**Pythonの学習の非常に早い段階。

于 2019-03-29T12:58:59.100 に答える
0

エクセルシートを読みたいコードを実行しようとしていました。問題は、say:SheetSumという名前のシートがないファイルがある場合、エラーの場所に移動できないということでした。私が書いたコードは次のとおりです。

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    try:
        print("Reading file: "+data_file)
        sheets['df_1'] = pd.read_excel(open(data_file,'rb'), 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

エラーを与える:

[WinError 32]ファイルが別のプロセスによって使用されているため、プロセスはファイルにアクセスできません

try except with finally私は完全なブロックを追加finallyし、次のような場合はファイルを閉じる必要があることを伝えなければなりませんでした:

def read_file(data_file):
    # data_file = '\rr\ex.xlsx'
    sheets = {}
    sheets_file = None
    try:
        print("Reading file: "+data_file)
        sheets_file = open(data_file,'rb')
        sheets['df_1'] = pd.read_excel(sheets_file, 'SheetSum')
    except Exception as excpt:
        print("Exception occurred", exc_info=True)
    finally:
        if sheets_file:
            sheets_file.close()
    return sheets

read_file(file)
shutil.move( file, dirpath +'\\processed_files')

それ以外の場合、ファイルはバックグラウンドで開いたままになります。

finallyが存在する場合は、クリーンアップハンドラーを指定します。try anyexceptおよび句を含む句が実行されますelse。いずれかの句で例外が発生し、処理されない場合、 例外は一時的に保存されます。finally句が実行されます。保存された例外がある場合は、finally 句の最後で再発生します。finally句で別の例外が発生した場合、保存された例外が新しい例外のコンテキストとして設定されます。

..詳細はこちら

于 2019-12-22T10:53:24.043 に答える
0

この回答に対するAbhijitSahuのコメントをよりよく表示し、構文を強調表示できるようにするためだけに、次のようにします。

このように、次の場合にどのコードブロックで何が起こるかを観察できます。

try: 
    x = Hello + 20 
    x = 10 + 20 
except: 
    print 'I am in except block' 
    x = 20 + 30 
else: 
    print 'I am in else block' 
    x += 1 
finally: 
    print 'Finally x = %s' %(x) 
于 2021-10-19T14:08:58.220 に答える