Pythonのコンテキストマネージャーで詳細に説明する

with このキーワードは、Pythonを学ぶすべての人によく知られています。

テキストオブジェクトを操作するとき、ほとんどの人がそれらを使用できるようにしますwith open。これはコンテキスト管理の例です。あなたはそれをかなりよく知っているに違いありません、そして私はもうナンセンスを話しません。

with open('test.txt') as f:
    print f.readlines()

1.どのコンテキストマネージャー?

基本的な文法

with EXPR as VAR:
    BLOCK

まず、いくつかの概念を明確にします

1. 上下文表达式:with open('test.txt') as f:
2. 上下文管理器:open('test.txt')
3. f 不是上下文管理器,应该是资源对象。

2.どのようにコンテキストマネージャー?

このようなコンテキスト管理を自分で実装するには、最初にコンテキスト管理プロトコルを知っている必要があります。

簡単に言うと、__enter__and__exit__メソッドはクラスに実装されており、このクラスのインスタンスはコンテキストマネージャーです。

たとえば、次の例:

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('===close resource connection===')

    def operate(self):
        print('===in operation===')

with Resource() as res:
    res.operate()

それを実行して、ログの印刷シーケンスを見てみましょう。実行プロセスを知ることができます。

===connect to resource===
===in operation===
===close resource connection===

この例から、コードを作成するときに__enter__、リソースの接続または取得をに入れて、リソースの終了をに書き込むことができることは明らかです__exit__

3.なぜコンテキストマネージャー?

勉強するときは、もう少し理由を自問し、知識のポイントについての理解を深めるのに役立つ詳細について考えてください。

なぜコンテキストマネージャーを使用するのですか?

私の意見では、これはPythonが提唱するエレガントなスタイルに関連しています。

  1. ファイル操作やデータベース接続など、より洗練された方法でリソースを操作(作成/取得/解放)できます。
  2. よりエレガントな方法で例外を処理できます。

1つ目は、すでにリソース接続を例として取り上げています。

2番目のタイプはほとんどの人に無視されます。ここで焦点を当てます。

ご存知のとおり、例外のtry...execept..処理は通常、プロセスのキャプチャに使用されます。これの欠点の1つは、コードのメインロジックに多数の例外処理エージェントが存在することです。これは、読みやすさに大きく影響します。

もう少し良いことは、with隠された例外を処理するために使用できます

上記のコード例に基づいて、1/0これを次のように一定会抛出异常的代码記述operateします。

class Resource():
    def __enter__(self):
        print('===connect to resource===')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('===close resource connection===')
        return True

    def operate(self):
        1/0

with Resource() as res:
    res.operate()

それを実行した後、エラーが報告されていないことに驚いた。

これは、コンテキスト管理プロトコルの強力な側面です。例外を__exit__キャッチして、それらをスローするか、ここで解決するかを決定できます。その__exit__見返りとしてTrue(Falseを返すためにデフォルトに戻らない)、Pythonインタープリターに通知するのと同じように、例外をキャプチャしました。破棄する必要はありません。

__exit__関数を作成するときは、それに注意を払う必要があります。関数には、次の3つのパラメーターが必要です。

  • exc_type:例外タイプ
  • exc_val:異常値
  • exc_tb:異常なエラースタック情報

メインロジックコードが例外を報告しない場合、これら3つのパラメーターはすべてNoneになります。

4.どのようにcontextlib?

上記の例では、コンテキストマネージャーを構築するためのクラスを作成しました。単純な関数を実装したいだけの場合、クラスの作成は少し複雑すぎます。現時点では、コンテキストマネージャーを実装するために1つの関数しか記述できないと考えました。

Pythonはこの点について長い間考えてきました。デコレータを提供します。コードプロトコルに従って関数コンテンツを実装する限り、この関数オブジェクトをコンテキストマネージャに変えることができます。

contextlibプロトコルに従って、ファイルを開くためのコンテキストマネージャーを実装します(開いた状態で)。

import contextlib

@contextlib.contextmanager
def open_func(file_name):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, 'r')

    # 【重点】:yield
    yield file_handler

    # __exit__方法
    print('close file:', file_name, 'in __exit__')
    file_handler.close()
    return

with open_func('/Users/MING/mytest.txt') as file_in:
    for line in file_in:
        print(line)

装飾された関数では、ジェネレーター(yield付き)である必要があり、yieldの前のコードは__enter__内部のコンテンツと同等です。イールド後のコードは__exit__、のコンテンツと同等です。

上記のコードは、コンテキストマネージャーの最初の目的(リソースの管理)のみを達成でき、2番目の目的(例外の処理)は達成できません。

例外を処理する場合は、次のように変更できます。

import contextlib

@contextlib.contextmanager
def open_func(file_name):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, 'r')

    try:
        yield file_handler
    except Exception as exc:
        # deal with exception
        print('the exception was thrown')
    finally:
        print('close file:', file_name, 'in __exit__')
        file_handler.close()

        return

with open_func('/Users/MING/mytest.txt') as file_in:
    for line in file_in:
        1/0
        print(line)

コンテキストマネージャーが言及されている限り、ほとんどの人はファイルを開く典型的な例について話すようです。

しかし、実際の開発では、使用できるコンテキストマネージャーの例がたくさんあります。私自身の例を挙げましょう。

OpenStackでは、仮想マシンのスナップショットを作成するときに、ローカルスナップショットイメージを保存するための一時フォルダーを作成する必要があります。ローカルスナップショットイメージが作成されたら、イメージをGlanceにアップロードします。次に、この一時ディレクトリを削除します。

このコードの主なロジックは创建快照、であり创建临时目录、前提条件删除临时目录属し、最後の仕上げです。

コードの量は少なく、ロジックは複雑ではありません创建临时目录,使用完后再删除临时目录が、プロジェクトの多くの場所で」関数が必要です。このロジック処理をコンテキストマネージャーとしてツール関数として記述できる場合、コードの再利用レートも大幅に向上します。

コードはこんな感じ

要約すると、コンテキストマネージャを使用することには3つの利点があります。

  1. コードの再利用率を向上させます。
  2. コードの優雅さを向上させます。
  3. コードの読みやすさを向上させます。

多数(300)のイラスト含まれているオリジナルの「PyCharmChinese Guide」e-bookをお勧めします。これはよくできていて、すべてのPythonエンジニアによるコレクションに値します。

アドレスは次のとおりです:http//pycharm.iswbm.com

おすすめ

転載: blog.csdn.net/weixin_36338224/article/details/108994968