2016-12-22 12 views
1

私は非同期プログラミングの例をpythonで説明しようとしていましたが、失敗しました。 ここに私のコードです。pythonでasync/awaitを使う方法+ +

Foo 
asyncFoo 

を10秒の待ち時間でasyncFooが表示されていた前に:

import asyncio 
import time 

async def asyncfoo(t): 
    time.sleep(t) 
    print("asyncFoo") 


loop = asyncio.get_event_loop() 
loop.run_until_complete(asyncfoo(10)) # I think Here is the problem 
print("Foo") 
loop.close() 

私の期待は、私が見るであろうということです。

しかし、代わりに私は10歳で何も得ていないし、両方とも表示しています。

私は何が間違っているのですか?どのように説明できますか?

+0

https://www.youtube.com/watch?v=ZzfHjytDceU私は保留にこの質問を置くために公正であるとは思わない –

+0

役に立つかもしれません。彼は明らかに、 "asyncFoo"の前に "Foo"を印刷したいと言っています。 – Eddie

+0

FWIW、 'time.sleep'も*ブロッキングです。 Asyncはスレッドをブロックしないで** IO **を待っている間に実行を再開するのに便利です。 –

答えて

7

run_until_completeは、asyncfooまでブロックされます。代わりに、2つのコルーチンがループ内で実行されている必要があります。 asyncio.gatherを使用すると、run_until_completeで複数のコルーチンを簡単に開始できます。ここで

は一例です:

import asyncio 


async def async_foo(): 
    print("asyncFoo1") 
    await asyncio.sleep(3) 
    print("asyncFoo2") 


async def async_bar(): 
    print("asyncBar1") 
    await asyncio.sleep(1) 
    print("asyncBar2") 


loop = asyncio.get_event_loop() 
loop.run_until_complete(asyncio.gather(async_foo(), async_bar())) 
loop.close() 
+0

これはクールです。私は両方のことを並行して実行する非同期関数にする必要があります。 – Rahul

-1

run_until_completeがブロックしています。だから、たとえそれが10秒で起こっても、それはそれを待つでしょう。完了後、もう1枚印刷されます。

「Foo」を以前に印刷したい場合は、loop.run_until_complete(asyncfoo(10))をスレッドまたはサブプロセスで起動する必要があります。

+0

私はPythonで非同期を使用することの複雑さとほとんど利益を見ません。なぜそれはノードのように簡単ではありませんか? – Rahul

+0

async *と* thread/subprocessを実行すると、この例ではポイントが失われます。 – Udi

2

コードフローとは無関係にコルーチンをTaskとして実行するコンテキストでは、期待通りの効果が得られます。 coroutinesを複数並べて実行している場合は、イベントループによってコード実行がawaitからawaitに変更されます。

例のコンテキスト内では、タスクオブジェクトにコルーチンをラップすることで、予想される動作を達成できます。タスクオブジェクトは、コードブロック内の残りのコードを保持せずにバックグラウンドで続行しますが呼び出されます。

たとえば、

import asyncio 

async def asyncfoo(t): 
    await asyncio.sleep(t) 
    print("asyncFoo") 

async def my_app(t): 
    my_task = asyncio.ensure_future(asyncfoo(t)) 
    print("Foo") 
    await asyncio.wait([my_task]) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(my_app(10)) 
loop.close() 

あなたの代わりにtimeモジュールのasyncio.sleep()を使用する必要があります注意してください。

+0

これはfooを出力しますが、asyncfooを印刷することはできません。 – Rahul

+0

タスクが完了する前に、イベントループが終了しています。イベントループを開いたままにする1つの方法は、 'loop.run_forever()'を使うことです。別の方法は、タスクを変数に割り当てることです。'my_task_var'を呼び出し、' await asyncio.wait(my_task_var) 'を使ってタスクが終了するのを待ちます。この場合、コード実行をブロックしない場所でタスク変数を待機します。 print( "Foo")ステートメントの後に置きます。 – shongololo

+0

@ Scripting.FileSystemObjectは、バージョンが自動的に動作し、自動的に終了するバージョンの回答を更新しました。 (数週間コンピュータから離れていた...) – shongololo

関連する問題