2017-01-21 10 views
1

Pythonのasyncioモジュールのイベントループが未処理タスクをどのように管理しているかについて質問があります。これは印刷されます実行Python asyncioタスクの注文

import asyncio 

@asyncio.coroutine 
def a(): 
    for i in range(0, 3): 
     print('a.' + str(i)) 
     yield 


@asyncio.coroutine 
def b(): 
    for i in range(0, 3): 
     print('b.' + str(i)) 
     yield 


@asyncio.coroutine 
def c(): 
    for i in range(0, 3): 
     print('c.' + str(i)) 
     yield 


tasks = [ 
    asyncio.Task(a()), 
    asyncio.Task(b()), 
    asyncio.Task(c()), 
] 

loop = asyncio.get_event_loop() 
loop.run_until_complete(asyncio.wait([t1, t2, t3])) 

:以下のコードを考えてみましょう、それは常に '' そしてその後、 'B' 'C' プリントアウトし

a.0 
b.0 
c.0 
a.1 
b.1 
c.1 
a.2 
b.2 
c.2 

ていることに注意してください。私は、各コルーチンが何回繰り返されても、常にその順序で印刷されることになります。だから、これはイベントループがここでそれが次に実行するタスクを決定するために使用する内部キューを維持していることを私に伝え、Node.jsの背景から来る

b.100 
c.100 
a.100 

ようなものを見ることはないと思います。最初にa()をキューの先頭に置き、b()、次にc()とします。これは、リスト内のタスクの順番がasyncio.wait()に渡されているためです。次に、yieldステートメントを実行するたびに、そのタスクがキューの最後に置かれます。より現実的な例では、非同期httpリクエストを行っている場合、http応答が戻った後にa()をキューの最後に戻すと言います。

私はこれに助言を得ることができますか?

答えて

1

現在、この例にはブロックI/Oコードは含まれていません。

import asyncio 


@asyncio.coroutine 
def coro(tag, delay): 
    for i in range(1, 8): 
     print(tag, i) 
     yield from asyncio.sleep(delay) 


loop = asyncio.get_event_loop() 

print("---- await 0 seconds :-) --- ") 
tasks = [ 
    asyncio.Task(coro("A", 0)), 
    asyncio.Task(coro("B", 0)), 
    asyncio.Task(coro("C", 0)), 
] 

loop.run_until_complete(asyncio.wait(tasks)) 

print("---- simulate some blocking I/O --- ") 
tasks = [ 
    asyncio.Task(coro("A", 0.1)), 
    asyncio.Task(coro("B", 0.3)), 
    asyncio.Task(coro("C", 0.5)), 
] 

loop.run_until_complete(asyncio.wait(tasks)) 

loop.close() 

ご覧のとおり、コルーチンは必要に応じてスケジュールされ、順序通りにスケジュールされていません。

+0

これは可能な限り早くコールバックを実行するため、I/Oが完了するのに異なる時間がかかると、順序が乱れるようになります。私の指摘は、(私の例のように)I/Oが起こっていなければ、舞台裏で起こっているタスク(おそらく待ち行列)の何らかの管理のために常に予測可能な順序で実行されるということでした。 OSスレッドスケジューラに従って実行されるスレッドのようなものとは対照的に、予測不能である。 – d512

+0

I/Oがない場合は、asyncioを使用しないでください。それらは予測可能ではなく、さまざまな実装やバージョン、または異なる条件でどのように動作するかを確認することはできません。 – Udi

+0

私は応答を感謝しますが、私の質問は 'asyncio'の適切な使い方ではなく、実装方法です。もちろん、ライブラリの実装の詳細については仮定を立てることは安全ではありません。この質問をすることによって、私はそうでないと示唆していませんでした。誰かがそれがどのように働いているか知っていたかどうかを知りたい – d512

関連する問題