元は容易ではない、ソースを明記してください
深入理解协程
説明するために、3つの部分に分かれ:
- コルーチンの紹介
- 達成コルーチンからの収量
- 非同期/非同期のawaitコルーチン
*この論文は、深入理解协程
最初の記事。
コルーチンとは何ですか
コルーチンは:英語はズタズタ、また、マイクロスレッドと呼ばれる、コルーチンと呼ばれ、軽量なスレッドは、ユーザー状態です。
これは、基本的にシングルスレッド化され、独自のレジスタコンテキストとスタックを持っています。私たちは、とき最後の呼び出し、各再入の際に、コールへの状態と同等の状態を保持することができます。
スレッドコンテキストスイッチのオーバーヘッドなしに、マルチプロセスと比較して、マルチスレッド、ロック機構を使用することなく、マルチスレッドと比べ。効率は、マルチプロセス、マルチスレッドよりも高いです。
最も簡単なコルーチン
python2.5を導入したとき、ジェネレータ(発電機)によって達成されます。最も単純な発電機のコルーチンで見てみましょうが実装されています。
>>> def coroutine(): # 注释一
print('-> coroutine started')
x = yield # 注释二
print('-> coroutine received:', x)
>>> c = coroutine() # 注释三
>>> c
<generator object coroutine at 0x03899230>
>>> next(c) # 注释四
-> coroutine started
>>> c.send(1) # 注释五
-> coroutine received: 1
Traceback (most recent call last):
File "<input>", line 1, in <module>
StopIteration # 注释六
なお、ジェネレータ関数定義されたコルーチンを使用して(yieldキーワードのための機能の必要性を):
注2:キーワードの左右への収率は、ユーザデータを受信するための左右を戻すための収量データを評価しました。ユーザーは、クライアント、そして降伏戻り値なしからのデータを受信した場合。
する注3ジェネレータを作成します。
コメント4:ちょうど前活性化を生成するためのニーズを作成したが、この呼び出し、next()
ファンクションジェネレータは、予め活性化されます。また、使用することができますc.send(None)
。
コメント5:事前の活性化が完了した後に、使用send()
時に算出した会計収率作成するために、関連スレッドで、入ってくるデータの機能を1
プログラムでは、次の利回り発現が表示され、プログラムが終了するまで実行し続けます。
VI注意:最後までプログラムを実行すると、スレッドはありません利回りキーワードの関連付けを作成するので、いつものようにリードジェネレータがスローStopIteration
例外を。
フォーコルーチンを述べて
GEN_CREATED
実行を開始するために待っている、完全に作成するための共同作成されたスレッド。
GEN_RUNNING
インタプリタが実行されます。
GEN_SUSPENDED
降伏式で一時停止します。
GEN_CLOSED
実行が終了します。
コルーチン現在のステータスinspect
照会モジュール。
以下は、より良好なコルーチンの挙動を理解するために、出力値の複数の例を与えます。
>>> from inspect import getgeneratorstate
>>> def coroutine(a):
print('-> started a=', a)
b = yield a
print('-> received: b=', b)
c = yield a + b
print('-> received: c=:', c)
>>> x = coroutine(1)
>>> getgeneratorstate(x)
'GEN_CREATED' # 注释一
>>> next(x)
-> started a= 1
1 # 注释二
>>> x.send(2)
-> received: b= 2
3 # 注释三
>>> getgeneratorstate(x)
'GEN_SUSPENDED' # 注释四
>>> x.send(3)
Traceback (most recent call last):
-> received: c=: 3
File "<input>", line 1, in <module>
StopIteration
>>> getgeneratorstate(x)
'GEN_CLOSED' # 注释五
注:だけで作成するための共同のスレッドも、ジェネレータを作成するGEN_CREATED
(コルーチンが開始されていない)状態。
注2:使用してnext(x)
作成する予備活性化COスレッド、ポーズを生成する第一のプログラムの実行、すなわち、戻り値です1
。
注3:x.send(2)
入力値を作成するスレッドの協会2
および変数に割り当てられb
、プログラム実行が第二のポーズを得るために、ここで戻りa+b
値を、です3
。
四注:降伏時秒間のポーズのこの時点で、それが作成するための共同のスレッドであるGEN_SUSPENDED
状態を。
コメント5:同時スレッド後例外関連付けを作成するために、スレッドの終了を引き起こし、スロー、従ってにある作成するGEN_CLOSED
状態。
終了コルーチン
コルーチンは、上記実際に、使用されてもよい、端部に投入される例示close()
の方法正常終了コルーチンを。
最初の例では、我々は、コードを変更します、
>>> from inspect import getgeneratorstate
>>> def coroutine():
print('-> coroutine started')
while True: # 注释一
x = yield
print('-> coroutine received:', x)
>>> c = coroutine()
>>> next(c)
-> coroutine started
>>> c.send(1)
-> coroutine received: 1
>>> c.send(2)
-> coroutine received: 2
>>> getgeneratorstate(c)
'GEN_SUSPENDED'
>>> c.close()
>>> getgeneratorstate(c)
'GEN_CLOSED' # 注释二
注:ここで終了を作成するために共同スレッドを避けるために、死のサイクルに参加します。
注2:それは行って見ることができclose()
RAが作成するスレッドになった後GEN_SUSPENDED
の状態を。そのコルーチン正常終了。
例外処理
throw()
この方法は、異常な渡すことができます。コード例を参照してください。
>>> class DemoException(Exception): # 注释一
'''定义的演示异常类型'''
pass
>>> def coroutine():
print('-> coroutine started')
while True:
try:
x = yield
except DemoException: # 注释二
print('*** DemoException handled. Continuing...')
else:
print('-> coroutine received:', x)
raise RuntimeError('This line should never run.') # 注释三
>>> c = coroutine()
>>> next(c)
-> coroutine started
>>> c.send(1)
-> coroutine received: 1
>>> c.throw(DemoException) # 注释四
*** DemoException handled. Continuing...
注:カスタム例外タイプDemoException
。
注2:特別な取り扱いDemoException
タイプ。
注3:この行が実行されることはありません。
コメント4:使用throw()
の着信例外タイプ。
最も原始的な実装では約Benpianは、達成するための面倒な例外処理が、コルーチンが、彼らは本当にコルーチン大きな利点を理解するために、コルーチン原理を実現しています。
パートIIは、方法をあなたと共有しますyield from
コルーチンを実装します。