別のスレッドで実行されているasyncio
イベントループで実行するタスクを非同期に挿入するにはどうすればよいですか?
私の動機は、インタプリタでインタラクティブな非同期ワークロードをサポートすることです。メインREPLスレッドをブロックできません。
私の現在の欠陥のある理解は、以下がうまくいくはずだと言っています。なぜそうではないのですか?上記の目標を達成するためのより良い方法は何ですか?
import asyncio
from threading import Thread
loop = asyncio.new_event_loop()
def f(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
t = Thread(target=f, args=(loop,))
t.start()
@asyncio.coroutine
def g():
yield from asyncio.sleep(1)
print('Hello, world!')
asyncio.async(g(), loop=loop)
異なるスレッドからのコールバックをスケジュールするには、call_soon_threadsafe
を使用する必要があります。
import asyncio
from threading import Thread
loop = asyncio.new_event_loop()
def f(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
t = Thread(target=f, args=(loop,))
t.start()
@asyncio.coroutine
def g():
yield from asyncio.sleep(1)
print('Hello, world!')
loop.call_soon_threadsafe(asyncio.async, g())
詳細は https://docs.python.org/3/library/asyncio-dev.html#asyncio-multithreading を参照してください。
EDIT:非同期ワークロードをサポートするインタープリターの例
# vim: filetype=python3 tabstop=2 expandtab
import asyncio as aio
import random
@aio.coroutine
def async_eval(input_, sec):
yield from aio.sleep(sec)
print("")
try:
result = eval(input_)
except Exception as e:
print("< {!r} does not compute >".format(input_))
else:
print("< {!r} = {} >".format(input_, result))
@aio.coroutine
def main(loop):
while True:
input_ = yield from loop.run_in_executor(None, input, "> ")
if input_ == "quit":
break
Elif input_ == "":
continue
else:
sec = random.uniform(5, 10)
print("< {!r} scheduled for execution in {:.02} sec>".format(input_, sec))
aio.async(async_eval(input_, sec))
loop = aio.get_event_loop()
loop.run_until_complete(main(loop))
loop.close()