私はいくつかのシェルコマンドを実行する必要があるスクリプトを持っています。しかし、コマンドが完了するのに時間がかかり過ぎると、強制的に殺さなければなりません。次のコードスニペットを考えてみましょう:asyncioはタイムアウト時にサブプロセスを終了します
import asyncio, random
q = asyncio.Queue()
MAX_WAIT = 5
@asyncio.coroutine
def blocking_task(sec):
print('This task will sleep {} sec.'.format(sec))
create = asyncio.create_subprocess_shell(
'sleep {s}; echo "Woke up after {s} sec." >> ./tst.log'.format(s=sec),
stdout=asyncio.subprocess.PIPE)
proc = yield from create
yield from proc.wait()
@asyncio.coroutine
def produce():
while True:
q.put_nowait(random.randint(3,8))
yield from asyncio.sleep(0.5 + random.random())
@asyncio.coroutine
def consume():
while True:
value = yield from q.get()
try:
yield from asyncio.wait_for(blocking_task(value), MAX_WAIT)
except asyncio.TimeoutError:
print('~/~ Job has been cancelled !!')
else:
print('=/= Job has been done :]')
loop = asyncio.get_event_loop()
asyncio.ensure_future(produce())
asyncio.ensure_future(consume())
loop.run_forever()
このコードは次のような出力を生成:
This task will sleep 4 sec.
=/= Job has been done :]
This task will sleep 8 sec.
~/~ Job has been cancelled !!
This task will sleep 5 sec.
~/~ Job has been cancelled !!
だから、彼らは仕上げに時間がかかりすぎる場合に予想される、ジョブが停止されているとして、それが働いているようです。
Woke up after 4 sec.
Woke up after 8 sec.
Woke up after 5 sec.
私は他のプロセスがなければならないとして、ログに一つだけの行があるはず期待:私は、ログをチェックすると、私はしかし、時間のかかるタスクを実行し続け、実際に中止された/殺した/停止されなかったことを確認することができます彼らが終了する機会を得る前に中止されました:
Woke up after 4 sec.
私は何をしたいのですか?
ここでもasyncio
が必要なのかわかりませんが、おそらくconcurrent.futures
も使用できます。いずれの方法でもタスクは同じです。タスクを終了します。タスクの終了には時間がかかりすぎます。
本当に美しく働いた、ありがとう!私はちょうど、なぜ私は 'asyncio.CancelledError'が私のコードで生成されたのか分かりませんでした。示されているように、出力は例外なく、きれいでした。 –
@NarūnasK私の編集を参照してください。 – Vincent