2017-11-24 19 views
1

以下は、2つのバックグラウンドタスクを実行する単純なasyncioループです。asyncio.wait_for()にタイムアウトが必要なのはなぜですか?

これらは両方とも単純なカウントを実行します。最初のものは永遠にカウントされ、 try/exceptで囲まれています。 2番目は5までカウントし、最初の1つをキャンセルし、 はループを停止します。

キャンセルが完了していることを確実にすることの2つの方法があります -

asyncio.wait([a sequence of futures]) 

asyncio.wait_for(a single future) 

どちらのオプションのタイムアウトを取るが。

タイムアウトなしで最初の方法を使用すると、キャンセルが完了し、 ループが停止します。

タイムアウトなしで2番目の方法を使用すると、将来はキャンセルされますが、 プログラムがハングします。

タイムアウトを2番目のタイムアウトに追加すると、最初のタイムアウトと同じ動作をします。

これには理由がありますか?

私はバージョン3.6.0を使用しています。

import asyncio 
from itertools import count 

async def counter1(): 
    cnt = count(1) 
    try: 
     while True: 
      print('From 1:', next(cnt)) 
      await asyncio.sleep(1) 
    except asyncio.CancelledError: 
     print('counter1 cancelled') 

async def counter2(): 
    cnt = count(1) 
    for i in range(5): 
     print('From 2:', next(cnt)) 
     await asyncio.sleep(1) 
    cnt1.cancel() 
# await asyncio.wait([cnt1]) # works 
# await asyncio.wait_for(cnt1) # hangs 
    await asyncio.wait_for(cnt1, 1) # works 
    loop.stop() 

loop = asyncio.get_event_loop() 
cnt1 = asyncio.ensure_future(counter1()) 
cnt2 = asyncio.ensure_future(counter2()) 
loop.run_forever() 
+0

私は答えの半分を考え出しました。 'timeout'はwait()を使うときはオプションの引数ですが、wait_for()を使うときは必要な引数です。したがって、asyncioは例外を発生させています。しかし、なぜ私はトレースバックが現れないのか分かりません。 –

答えて

1

私は、comp.lang.python上で以下の答えを受けた -

「未処理の例外が時にループが終了警告として示されているがあるかもしれないので、それは、その前に表示することはできません。まだスケジュールされていないタスクであっても、counter2タスクの結果を取得してその例外を処理しようとする可能性がある他のタスクもあります。

私はWindowsでテストしていました。私はCtrl-CをWindows上で動作させることは決してなかったので、Ctrl-Pauseを使用します。これは、保留中のトレースバックを表示せずにインタープリタをクラッシュさせます。

Linuxでプログラムを実行してCtrl-Cを押すと、トレースバックが表示されます。最初にLinux上でテストを行った場合、元の質問を投稿する必要はありませんでした。

関連する問題