Veuillez expliquer “la Tâche a été détruit, mais il est en attente!”

Python 3.4.2

Je suis en train d'apprendre asyncio et je l'utilise pour la permanence d'écouter de la CIB en bus, tandis que gbulb à l'écoute de la dbus.

Quelques remarques:

J'ai donc créé une fonction listen_to_ipc_channel_layer que la permanence d'écoute pour les messages entrants sur la CIB canal et passe le message à un message_handler.

Je suis également à l'écoute de SIGTERM et SIGINT. Alors quand j'ai envoyer un signal SIGTERM à l'python processus en cours d'exécution le code que vous trouverez au bas, le script doit se terminer normalement.

Le problème

... Je vais avoir est l'avertissement suivant:

got signal 15: exit
Task was destroyed but it is pending!
task: <Task pending coro=<listen_to_ipc_channel_layer() running at /opt/mainloop-test.py:23> wait_for=<Future cancelled>>

Process finished with exit code 0

... avec le code suivant:

import asyncio
import gbulb
import signal
import asgi_ipc as asgi

def main():
    asyncio.async(listen_to_ipc_channel_layer())
    loop = asyncio.get_event_loop()

    for sig in (signal.SIGINT, signal.SIGTERM):
        loop.add_signal_handler(sig, ask_exit)

    # Start listening on the Linux IPC bus for incoming messages
    loop.run_forever()
    loop.close()

@asyncio.coroutine
def listen_to_ipc_channel_layer():
    """Listens to the Linux IPC bus for messages"""
    while True:
        message_handler(message=channel_layer.receive(["my_channel"]))
        try:
            yield from asyncio.sleep(0.1)
        except asyncio.CancelledError:
            break

def ask_exit():
    loop = asyncio.get_event_loop()
    for task in asyncio.Task.all_tasks():
        task.cancel()
    loop.stop()


if __name__ == "__main__":
    gbulb.install()
    # Connect to the IPC bus
    channel_layer = asgi.IPCChannelLayer(prefix="my_channel")
    main()

Encore je ne comprends que très peu de asyncio, mais je pense que je sais ce qui se passe. En attendant yield from asyncio.sleep(0.1) le gestionnaire de signal pris la SIGTERM et dans ce processus, il appelle task.cancel().

Question jeté dans: Ne devrait pas déclencher la CancelledError dans le while True: boucle? (Parce qu'il ne l'est pas, mais c'est comme ça que je comprends "L'appel de l'annuler() va lancer une CancelledError à la enveloppé coroutine").

Finalement loop.stop() est appelé, ce qui arrête la boucle, sans attendre que soit yield from asyncio.sleep(0.1) pour retourner un résultat ou même l'ensemble de la coroutine listen_to_ipc_channel_layer.

S'il vous plaît corrigez-moi si je me trompe.

Je pense que la seule chose que je dois faire est de faire de mon programme d'attendre le yield from asyncio.sleep(0.1) pour retourner un résultat et/ou coroutine de sortir le tout en boucle et terminer.

Je crois que je confonds beaucoup de choses. Merci de m'aider à faire ces choses afin que je puisse comprendre comment gracieusement fermer la boucle d'événement sans avertissement.

OriginalL'auteur Daniel | 2016-11-30