web-dev-qa-db-fra.com

Envoyer des tâches asynchrones à la boucle en cours d'exécution dans un autre thread

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.

Exemple

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)
22
MRocklin

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()
10
Jashandeep Sohi