Python-try...finally... とwith

5355 ワード

try…finally…
大きな一連のコードを実行すると、プログラムコードの一部がエラーになるとすぐに停止し、残りの他のコードも実行を続行しません.これには、残りの未実行のコードの中に、解放前に割り当てられたメモリなど、実行しなければならないことがある場合、エラーによる後のコードの実行ができないため、メモリの漏洩などの影響があります.だからtryを使って...finally...,tryのコードは、エラーが発生したかどうかにかかわらず、finally部分のコードの実行に影響しません.つまり、finallyセクションのコードはいずれも実行され、finallyで実行を保証するために必要なことを実行することができます.
 
with
try...finally...上記の問題は解決できますが、コードが長すぎます.もう一つ上記の問題を解決する方法があります.それはwithです.
with文はリソースにアクセスする場合に適用され、使用中に異常が発生したかどうかにかかわらず必要な「クリーンアップ」操作を実行し、ファイルの使用後に自動的に閉じる、スレッド内のロックの自動取得と解放などのリソースを解放することを確保します.
with文を使用するには、まずコンテキストマネージャという概念を理解する必要があります.コンテキストマネージャがあればwith文が機能します
 
  • コンテキストマネージャおよびwith文に関する概念
  • のセット
     
  • コンテキスト管理プロトコルContext Management Protocol:メソッドを含む_enter__()と_exit__()は、このプロトコルをサポートするオブジェクトがこの2つの方法を実装します.
  • コンテキストマネージャContext Management:コンテキスト管理プロトコルをサポートするオブジェクト_enter__()と_exit__()この2つの方法.コンテキストマネージャは、with文を実行するときに実行時を確立するコンテキストを定義し、with文ブロックコンテキストの入力と終了操作を実行します.通常with文を使用してコンテキストマネージャを呼び出します.メソッドを直接呼び出すことで使用することもできます.
  • ランタイムコンテキストRuntime Context:コンテキストマネージャによって作成され、コンテキストマネージャの_enter__()と_exit__()メソッド実装、_enter__()文体実行前にランタイムコンテキストに入る_exit__()文体の実行が完了すると、実行時コンテキストから終了します.with文は、ランタイムコンテキストという概念をサポートします.
  • コンテキストエクスプレッションContext Expression:with文のキーワードwithに続くエクスプレッションは、コンテキストマネージャオブジェクト
  • である必要があるコンテキストエクスプレッションです.
  • 文体With-Body:with文に包まれたコードブロックは、文体を実行する前にコンテキストマネージャの__を呼び出すenter__()メソッドは、文体を実行した後に実行されます_exit__()メソッド
  •  
  • 基本文法と動作原理
  • with文の構文フォーマットは次のとおりです.
  • with文の構文フォーマット
  • with context_expression [as target(s)]:
        with-body
    ここでcontext_expressionは、as句のtarget(s)に値を付けないコンテキストマネージャオブジェクトを返します.as句を指定すると、コンテキストマネージャの_enter__()メソッドの戻り値はtarget(s)に割り当てられます.target(s)は、単一の変数であってもよいし、「()」で囲まれたメタグループであってもよい(「,」で区切られた変数リストであってはならず、「()」を付けなければならない.
    Pythonはいくつかの組み込みオブジェクトを改良し、コンテキストマネージャのサポートを追加し、with文に使用できます.例えば、ファイルを自動的に閉じることができ、スレッドロックの自動取得と解放などです.
    ファイルを操作する場合は、with文を使用して次のコードを使用します.
  • with文を使用してファイルオブジェクト
  • を操作する
    with open(r'somefileName') as somefile:
        for line in somefile:
            print line
            # ...more code

    ここではwith文を使用し、ファイルの処理中に異常が発生したかどうかにかかわらず、with文の実行が完了した後に開いているファイルハンドルが閉じられていることを保証します.従来のtryを使うと...finally...,次のようなコードを使用します.
  • try...finally...モード操作ファイルオブジェクト
  • somefile = open(r'somefileName')
    try:
        for line in somefile:
            print line
            # ...more code
    finally:
        somefile.close()

    比較するとwith文を用いることで符号化量を減らすことができる.コンテキスト管理プロトコルのサポートには、モジュールthreading、decimalなどが追加されています.
  • with文実行プロセス
  • context_manager = context_expression
    exit = type(context_manager).__exit__  
    value = type(context_manager).__enter__(context_manager)
    exc = True   # True       ,        ;False         ,         
    try:
        try:
            target = value  #       as   
            with-body     #    with-body
        except:
            #           
            exc = False
            #    __exit__    True,      ;     False,       
            #             
            if not exit(context_manager, *sys.exc_info()):
                raise
    finally:
        #     ,     statement-body    break/continue/return     
        #         
        if exc:
            exit(context_manager, None, None, None) 
        #      None,None            False
    

     
    with文を使用してtryに相対...finally...簡単に言えば、with文が背後で多くの仕事をしているため、ユーザー一人一人がf.close()を書いてファイルを閉じる必要はありません.with文のcontext_expressionはコンテキストマネージャです.これは後述します.with文の[as variable]はオプションで、as variable説明子を指定した場合、variableはコンテキストマネージャcontext_expression呼び出し_enter__()関数で返されるオブジェクト.したがって、fは必ずしもexpressionではなくcontext_expression.__enter__()の戻り値、context_についてexpression.__enter__()何を返すかはこの関数で決まる.with-blockは実行文、with-blockが完了するとwith文は自動的にリソースクリーンアップされ、上記の例ではwith文は自動的にファイルを閉じます
    次にwith文が背後で無名で何をしたのかを具体的に話します.さっきcontextと言いましたexpressionはコンテキストマネージャであり、実装されています.enter__および_exit__2つの関数.with文を呼び出すと、次のように実行されます.
  • 実行context_expression、コンテキストマネージャcontext_を生成manager
  • コンテキストマネージャを呼び出す_enter__()メソッドas句を使用すると、enter__()メソッドの戻り値はas句のtarget(s)
  • に与える.
  • 実行文体with-body
  • 実行中に異常が発生したかどうかにかかわらず、コンテキストマネージャの_を実行します.exit__()メソッド、_exit__()メソッドは、リソースの解放などの「クリーンアップ」作業を担当します.実行中に例外が発生しなかったり、文体で文break/continue/returnが実行されていたりした場合は、Noneをパラメータとして__を呼び出します.exit__(None, None, None) ;実行中に異常が発生した場合はsysを使用する.exc_infoで得られた異常情報はパラメータ呼び出し_exit__(exc_type, exc_value, exc_traceback)
  • に異常が発生した場合、_exit__(type,value,traceback)Falseを返すと、例外が再び投げ出され、with以外の文論理で例外を処理させるのも一般的な方法です.Trueを返すと、例外は無視され、例外は処理されなくなる
  • .
    with文はファイルだけでなく、ロック、接続なども管理できます
     
    だからこんなにたくさん言ったのに、いったいコンテキストマネージャとは何ですか.
    コンテキストマネージャ
    コンテキストマネージャはコンテキストプロトコルを実装するクラスであり、コンテキストプロトコルはクラスを実装する_enter__()と_exit__()2つの方法.一つのクラスが実現すれば_enter__()と_exit__()をコンテキストマネージャと呼びます
    次の2つの方法を具体的に説明します.
  • __enter__():主にいくつかの環境準備作業を実行し、リソースオブジェクトを返します.コンテキストマネージャopen(「test.txt」)の_enter__()関数はファイルオブジェクトを返します._enter__()は、異なるexpressionオブジェクトに基づいて異なる値
  • を返します.
  • __exit__():完全な形式は__です.exit__(type,value,traceback)の3つのパラメータは、それぞれ異常タイプ、異常情報、スタックです.実行体文に異常が発生していない場合、この3つのパラメータはNoneに設定されます.そうでなければ、コンテキストの例外情報が含まれます._exit_()メソッドはTrueまたはFalseを返し、それぞれ開始された例外が処理されているかどうかを示し、Falseを返すと、開始された例外はコンテキストに渡されます.もし__exit__()関数内部で異常が発生すると,実行体の中で発生した異常が上書きされる.例外を処理する場合、例外を再放出する必要はありません.Falseに戻るだけです.with文は__を検出します.exit__()Falseを返して例外を処理します.

  • コンテキストマネージャをカスタマイズするには、クラスを定義して実行するだけです.enter__()と_exit__()でいいです.