Comment puis-je insérer des tâches de manière asynchrone à exécuter dans une boucle d'événements asyncio
s'exécutant dans un autre thread?
Ma motivation est de prendre en charge des charges de travail asynchrones interactives dans l'interpréteur. Je ne peux pas bloquer le fil principal REPL.
Ma compréhension imparfaite actuelle dit que ce qui suit devrait fonctionner. Pourquoi pas? Quelle est la meilleure façon d'atteindre l'objectif ci-dessus?
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)
Tu dois utiliser call_soon_threadsafe
pour planifier des rappels à partir de différents threads:
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())
Voir https://docs.python.org/3/library/asyncio-dev.html#asyncio-multithreading pour plus d'informations.
EDIT: Exemple d'interpréteur prenant en charge les charges de travail asynchrones
# 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()