Quantcast
Channel: Active questions tagged zeromq - Stack Overflow
Viewing all articles
Browse latest Browse all 193

cancelling asyncio.wait in combination with set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

$
0
0

I'm trying to make a code template which sends a heartbeat to some external things by ZMQ on win32 and linux.

On win32 I must use the asyncio.WindowsSelectorEventLoopPolicy() because of zmq and zmq.asyncio, however this seems to break the ctrl-c task cancelling behavior if there's an asyncio.await in my code. (The tasks dict is a global one because I want to access it from some tasks too).

If I leave out the asyncio.WindowsSelectorEventLoopPolicy() then the ctrl-c behavior in association with asyncio.wait works. So the culprit is definitely this loop selector.

How can I change my code so I have the best of both worlds. I.e. and using the selectoreventloop (or a loop which is compatible with zmq) and have a correct ctrl-c behavior ?

Below is my complete test code (python 3.10.9) :

# TEST CODEimport asyncioimport nest_asyncioimport zmq, zmq.asyncioimport sysfrom colorama import Fore, Back, Style, initimport pprintimport signaldef signal_handler(signal, frame):    print(f"Signal handler called")    raise KeyboardInterruptasync def heartbeat(pub, mqtt_Q, mySQL_Q, influx_Q, exit_event):    global counter    try:        while not exit_event.is_set():            counter += 1            print (f"Heartbeat {counter:3} send")            # // Logic to send heartbeats here            for _ in range(10):                await asyncio.sleep(1)    except asyncio.CancelledError:        print (f"Cleanup here")async def main():    try:        task_functions = {"Heartbeat": heartbeat(zmq_publish, mqtt_Q, mySQL_Q, influx_Q, exit_event),        }        for taskname, coro in task_functions.items():            tasks[taskname] = asyncio.create_task(coro)        print(f"\n<DEBUG LINE BELOW>\n")        pprint.pp(tasks)        print(f"\n")        await asyncio.gather(*tasks.values())    except KeyboardInterrupt:        print(f"Keyboard interrupt !!")    finally:        # Clean up tasks on interrupt        for task in asyncio.all_tasks():            task.cancel()        # Ensure all tasks are cancelled and cleaned up        await asyncio.gather(*tasks.values(), return_exceptions=True)# <==== SETUP BELOW ====>init(True)myIdCode = 'dmp-001'zmq_publish = 'placeholder'counter = 0mqtt_Q = asyncio.Queue()mySQL_Q = asyncio.Queue()influx_Q = asyncio.Queue()exit_event = asyncio.Event()tasks = {}if sys.platform != "win32":    import uvloop    signal.signal(signal.SIGTERM, signal_handler)else:    import winloop    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())asyncio.run(main())`

At first I used

await asyncio.sleep(10) but i changed it to

for _ in range(10):     await asyncio.sleep(1)

to have a better responsiveness, however, this is a solution which reduces the timeout to 1sec but isn't a real fix.


Viewing all articles
Browse latest Browse all 193

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>