より良いプレゼンテーションのために、私は、次の3つの機能、同期機能、2つの非同期機能を用意し
#DEFINEは、ブロッキング機能 :DEFピング(URL) ("ブロッキング機能の実行を開始する")印刷を time.sleep(2) os.system( "ピング%のS" %のURL) を印刷( "実行終了機能をブロックする") の#define 2を非同期機能 非同期DEFのasyncfunc1(): 印刷( "一時停止関数func1") (1)のawaitのasyncio.sleep 印刷( "FUNCの関数func1"、threading.current_thread()) を印刷( '再開関数func1') リターン"関数func1" 非同期DEFのasyncfunc2 (): 印刷( "一時停止関数func2") のawaitのasyncio.sleep(1) 印刷( "FUNCの関数func2"、threading.current_thread()) を印刷( '再開関数func2') リターン"関数func2"
制御タスクコルーチン
シングルタスクコルーチンを実行します
上記の機能は、例えば、私は()関数の実行をasyncfunc1し、結果を取得したい、あなたが使用できるloop.create_task()
タスクオブジェクトを作成する方法を、タスク先物呼び出すときにサブクラスであるloop.run_until_complete()
コルーチン終了後、後により、task.result()
コルーチン機能を取得結果を返します。
非同期DEF asyncfunc1(): プリント( "一時停止関数func1") (1)asyncio.sleepを待つ 印刷( "FUNC関数func1"、threading.current_thread()) プリント( '再開関数func1') リターン"関数func1" __name場合__ == "__ MAIN__ ": 印刷("メインスレッドで」、threading.current_thread()) ループ= asyncio.get_event_loop() タスク= loop.create_task(asyncfunc1()) loop.run_until_complete(タスク) プリント( "タスクの結果"である、task.result ())
出力は、
メインスレッドで<_mainthread(mainthreadは、 "6140 =" =開始) "">サスペンド関数func1 FUNC関数func1 <_mainthread(mainthread、開始= "" 6140)= ""> func1のタスク結果を再開関数func1あります
そして、メインスレッドは、同じスレッドでコルーチン機能を実行しています。
また、オブジェクトをタスクにコールバックメソッドを追加することができます
#coding:GBKの asyncioインポート インポート時間、SYS 非同期DEF asyncfunc1(): プリント( "サスペンド関数func1")は asyncio.sleep(1)待つ プリント( "FUNC関数func1"、threading.current_thread()) プリント( '再開関数func1')を リターン"関数func1" #定义一个回调函数 デフcallbackfunc(タスク): プリント( "タスク运行结束、它的结果是:"、task.result()) であれば__name __ == "__ MAIN__": 印刷( "メインスレッドで" 、threading.current_thread()) ループ= asyncio.get_event_loop() タスク= loop.create_task(asyncfunc1()) task.add_done_callback(callbackfunc) loop.run_until_complete(タスク)
出力は、
メインスレッドで<_mainthread(mainthreadは、 "=開始" 11248)= "">
中断関数func1
FUNCをfunc1の<_mainthread(mainthreadは、 "=開始" 11248)= "">
関数func1を再開
タスクの終了を実行し、その結果は以下のとおりです。関数func1
loop.run_until_complete
ブロッキング方法があり、それがコルーチンは、このメソッドの最後まで走るの内側にある場合にのみ終了した後、コードが後に実行されます。
実際には、あなたが呼び出すことができませんloop.run_until_complete
、メソッドの後にタスクを作成し、実際には、実行中のコルーチン機能であったが、時にイベントループ準備実行を開始する場合は、この時間タスクの状態をpending
、イベントループを呼び出さない場合は、しないでくださいコルーチン機能を実行し、メインスレッド仕上げので、サブスレッドは、次のような書かれたコードのように、破壊されます。
もし__name __ == "__ MAIN__": 印刷( "メインスレッドで"、threading.current_thread()) ループ= asyncio.get_event_loop() タスク= loop.create_task(asyncfunc1()) time.sleep(3)
結果として出力されます
メインスレッドで<_mainthread(mainthread、開始= "" 6056)= "">
タスクが破壊されたが、それは保留されています!
仕事:
CB = [test.py:39でcallbackfunc()]>
SYS:1:RuntimeWarning:コルーチン 'asyncfunc1' 待望ていませんでした
だから、コルーチン機能が実装されているようにしたい、あなたは上記のタスクを実行するためにイベントループを呼び出す必要がありloop.run_until_complete
、それサイクルを実行し始めたようにすることです、実際には、使用することもできloop.run_forever()
、その名が示すように、この機能を、常に実行します。唯一のイベントループがアップ実行し、登録されたコルーチンが実装されるサイクルを使用しますが、あればloop.run_forever()
、それはここにバックアップします、イベントループがあるstop
方法、サイクルの終わりに、我々は、対象タスクにコールバックメソッドを追加することができますイベントループを呼び出すときにコルーチンの実行が終了した後、stop
全体のサイクルを終了する方法を
#coding:GBKの asyncioインポート インポート時間、SYS 非同期DEF asyncfunc1(): プリント( "サスペンド関数func1")は asyncio.sleep(1)待つ プリント( "FUNC関数func1"、threading.current_thread()) プリント( '再開関数func1')を リターン"関数func1" #定义一个回调函数 デフcallbackfunc(タスク): プリント( "タスク运行结束、它的结果是:"、task.result()) loop.stop() __name __ == "__ MAIN__"の場合: プリント( "メインスレッドで"、threading.current_thread()) ループ= asyncio.get_event_loop() タスク= loop.create_task(asyncfunc1()) task.add_done_callback(callbackfunc) loop.run_forever()
使用に加えて、loop.run_until_complete
この方法を使用してもよいasyncio.ensure_future()
上記のコードを実行する方法のコルーチンをtask = loop.create_task(asyncfunc1())
するためにtask = asyncio.ensure_future(asyncfunc1())
同じ結果を得るには、タスク・オブジェクトは、先物サブクラスタスクとして渡すことができる、コルーチンオブジェクトまたはパラメータ先物であり、着信時にコルーチンオブジェクトで、タスクオブジェクトを返し先物が直接オブジェクトを返すとき、先物を渡すと、それは呼び出しで、と言うことですasyncio.ensure_future()
後で、それはコールバックメソッドを追加できるというタスクオブジェクトを返します。そして(タスクが実行されていない場合、最終的な結果は、メソッドが例外をスローしますと呼ばれていることに注意してください)結果を得るためにtask.result()メソッドを呼び出すことができます。
平行コルーチンにおける複数のタスク
私はどのようにそれが動作しないことを同時にこれら二つの機能を実行し、その戻り値を取得したい場合、私は、上の2つの非同期機能のasyncfunc1とasyncfunc2を持っていますか?
上記単一コルーチンの経験により、我々はまた、()run_foreverで実行され、その後、2つのタスクサイクルを作成するためにイベントを使用することができます、あなたはタスクにコールバックを追加し、その結果を出力することができます。
#coding:GBK インポートASYNCIOの #は、2つの非同期関数を定義 )(非同期DEFのasyncfunc1: 印刷( "サスペンド関数func1") のawaitのasyncio.sleep(1) プリント( "FUNCの関数func1"、threading.current_thread()) プリント(「関数func1を再開します') リターン"関数func1" 非同期DEFのasyncfunc2(): 印刷( "一時停止関数func2") のawaitのasyncio.sleep(1)。 印刷( "FUNCの関数func2"、threading.current_thread()) を印刷('再開関数func2「) リターン"関数func2" #コールバック関数を定義する DEFのcallbackfunc(タスク): 印刷( "タスクの実行の終了を、それが結果は次のとおりです。"、task.result()) IF __name__ __ == "__ MAIN__": 印刷( "「メインスレッドで、threading.current_thread()) ループ= ASYNCIO。get_event_loop() TASK1 = loop.create_task(asyncfunc1()) task1.add_done_callback(callbackfunc) タスク2 = loop.create_task(asyncfunc2()) task2.add_done_callback(callbackfunc) loop.run_forever()
出力は、
メインスレッドで<_mainthread(mainthread、開始= "" 8040)= "">
中断関数func1
中断func2の
FUNC func1の<_mainthread(mainthreadは、 "=開始" 8040)= "">
関数func1を再開
FUNC func2の<_mainthread(mainthreadは、 "=開始" 8040)= "">
func2の再開
タスクの終了を実行し、その結果は以下のとおりです。関数func1
タスクの終了を実行し、その結果は以下のとおりです。func2の
ループによるこの時間は、メソッドをrun_foreverと呼ばれ、stopメソッドを呼び出す方法はありませんので、プログラムがカードを持っています。
そのようなプロセスは、同時実行の複数であってもよいが、そのようなプロセス複雑一つは、第二の結果を回復するために便利ではありません。
asyncio集まるのawait asyncio.gather(*)は、それはすべての結果を返します呼び出すときに、複数のタスクオブジェクトを渡すことができる方法があります
新しい関数を作成する必要もあるので、唯一の待つ非同期デフ機能に書くことが原因
非同期DEFメイン(): TASK1 = loop.create_task(asyncfunc1()) task1.add_done_callback(callbackfunc) タスク2 = loop.create_task(asyncfunc2()) task2.add_done_callback(callbackfunc) 結果=待つasyncio.gather(タスク1、タスク2) 印刷(結果) 非同期DEF mian2(): 結果=待つasyncio.gather(asyncfunc1()、asyncfunc2()) プリント(結果)
両方の定義は方法があり、一つは、伝達関数を収集することであるコルーチンオブジェクトは、タスクオブジェクトに渡されています。呼び出した後
もし__name __ == "__ MAIN__": 印刷( "メインスレッドで"、threading.current_thread()) ループ= asyncio.get_event_loop() loop.run_until_complete(メイン())#またはメイン2()
結果として出力されます
メインスレッドで<_mainthread(mainthread、開始= "" 7016)= "">
中断関数func1
中断func2の
FUNC func1の<_mainthread(mainthreadは、 "=開始" 7016)= "">
関数func1を再開
FUNC func2の<_mainthread(mainthreadは、 "=開始" 7016)= "">
func2の再開
タスクの終了を実行し、その結果は以下のとおりです。関数func1
タスクの終了を実行し、その結果は以下のとおりです。func2の
[ 'func1の'、 'func2の']
これは、並列コルーチンの回復と結果を実現しています。
ここでは簡単に導入されたこの記事では、その後、同期コードの実装を分析していきます。