Issue
My example class uses only two methods,
async def run()
: creates a asyncio.Future() and awaits itdef stop()
: sets the result of the Future() created by the run() method
The idea is to use the python signal handler to call the stop()
function once a signal is received. The stop()
then sets the result of the Future() the run()
is waiting for. So far so good, but this does not work. Actually, the run()
method never notices that the Future() is done.
Example code:
import asyncio
import signal
class Foo:
def __init__(self):
self._stop = None
async def run(self):
print(f"1. starting foo")
self._stop = asyncio.Future()
await self._stop
print(f"4. 'stop' called, canceling running tasks...")
def stop(self):
print(f"3. stopping foo")
self._stop.set_result(None)
f = Foo()
loop = asyncio.new_event_loop()
def signal_handler(_, __):
print(f"2. signal handler: call Foo.stop()")
f.stop()
signal.signal(signal.SIGINT, signal_handler)
loop.run_until_complete(f.run())
print(f"5. bye")
and the output is:
1. starting foo
2. signal handler: call Foo.stop()
3. stopping foo
That's it. The fourth print entry is never called. Although the self._stop
Future is done
after setting the result.
Does anyone have any idea what I am doing wrong and what I am missing? Any help would be greatly appreciated!
Solution
I cannot reproduce your problem, but it is quite possible that it'll happen on different operating systems.
Unlike signal handlers registered using
signal.signal()
, a callback registered with this function is allowed to interact with the event loop.
The usual culprit that causes those issues is the event loop not waking up from outside input.
There are 2 solutions for your issue:
- If you're using unix, change
signal.signal()
toloop.add_signal_handler()
. - If not, try changing
f.stop()
toloop.call_soon_threadsafe(f.stop)
. It will make sure that the event loop wakes up correctly.
Irrespective to that, you have a couple of different issues arising from using asyncio.new_event_loop()
and not assigning the loop to the thread or cleaning up correctly. I suggest you to use asyncio.run()
.
Answered By - Bharel
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.