web-dev-qa-db-fra.com

RuntimeError: il n'y a pas de boucle d'événement en cours dans le thread 'Thread-1', erreur de multithreading et asyncio

J'ai un thread qui appelle des boucles asyncio, mais cela provoque l'exception mentionnée:

RuntimeError: There is no current event loop in thread 'Thread-1'.

Cette question: RuntimeError: Il n'y a pas de boucle d'événement en cours dans le thread en async + apscheduler est tombé sur le même problème, mais ils se référaient à un planificateur que je n'ai pas.

Mon code est le suivant:

def worker(ws):
      l1 = asyncio.get_event_loop()
      l1.run_until_complete(ws.start())  


      l2 = asyncio.get_event_loop()
      l2.run_forever()


if __name__ == '__main__':
    ws = Server()
    p = threading.Thread(target=worker,args=(ws,))
    p.start()


    while True:
        try:
            #...do sth
        except KeyboardInterrupt:
            p.join()
            exit() 
7
Kev1n91

Le nouveau thread n'a pas de boucle d'événement, vous devez donc le passer et le définir explicitement:

def worker(ws, loop):
    asyncio.set_event_loop(loop)
    loop.run_until_complete(ws.start())

if __name__ == '__main__':
    ws = Server()
    loop = asyncio.new_event_loop()
    p = threading.Thread(target=worker, args=(ws, loop,))
    p.start()

De plus, p.join() ne terminera pas votre script correctement car vous n'arrêtez jamais le serveur afin que votre boucle continue de fonctionner, probablement en raccrochant le thread. Vous devez appeler smth comme loop.call_soon_threadsafe(ws.shutdown) avant de rejoindre le thread, en attendant idéalement l'arrêt progressif du serveur.

12
hoefling

Sous Windows avec Python 3.7.3, au lieu de créer la boucle d'événements directement dans le thread,

Je dois:

asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

Sinon, le problème persisterait.

1
kakyo

J'ai eu ce problème pour exécuter un serveur Bokeh dans un thread. Lorsque j'essayais de créer le serveur = serveur ({'/': app}, port = 0), j'obtenais cette erreur. De la documentation Tornado, j'ai trouvé ce qui suit ...

Class tornado.platform.asyncio.AnyThreadEventLoopPolicy[source]

Politique de boucle d'événement qui permet la création de boucle sur n'importe quel thread. La stratégie de boucle d'événement asyncio par défaut crée uniquement automatiquement des boucles d'événement dans les threads principaux. D'autres threads doivent créer des boucles d'événements de manière explicite, sinon asyncio.get_event_loop (et donc IOLoop.current) échouera. L'installation de cette stratégie permet de créer automatiquement des boucles d'événements sur n'importe quel thread, correspondant au comportement des versions de Tornado antérieures à 5.0 (ou 5.0 sur Python 2).

Usage:

asyncio.set_event_loop_policy(AnyThreadEventLoopPolicy())

http://www.tornadoweb.org/en/stable/asyncio.html#tornado.platform.asyncio.AnyThreadEventLoopPolicy

0
joltman