2

I have a program which executes some long-running, synchronous tasks and may need to exit even when some of those tasks haven't finished yet. The following is a simple program which start such a task in main(). main() immediately returns after that and thus the program should exit.

import asyncio, time

def synchronous_task():
    for i in range(5):
        print(i)
        time.sleep(1)

async def main():
    loop.run_in_executor(None, synchronous_task)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

print('Main thread exiting.')

But instead I get this when running the script:

$ python3.5 test3.py 
0
Main thread exiting.
1
2
3
4

What is the intended way to handle such a situation? The event loop's default executor already uses daemon threads and terminating the program without cleanup would be OK in my case, but I don't want to use os._exit().

Feuermurmel
  • 9,490
  • 10
  • 60
  • 90

1 Answers1

0

Your question more about how to kill a thread. Look for this post for details.

Solution with event would be:

import asyncio, time
from functools import partial
import threading
import concurrent


def synchronous_task(ev):
    for i in range(5):
        if ev.isSet():
            print('terminating thread')
            return
        print(i)
        time.sleep(1)

async def main():
    ev = threading.Event()  # see: https://stackoverflow.com/a/325528/1113207

    loop.run_in_executor(None, partial(synchronous_task, ev))
    await asyncio.sleep(2)  # give thread some time to execute, to see results

    ev.set()


loop = asyncio.get_event_loop()
executor = concurrent.futures.ThreadPoolExecutor(5)
loop.set_default_executor(executor)
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    executor.shutdown(wait=True)  # see: https://stackoverflow.com/a/32615276/1113207
    loop.close()

print('Main thread exiting.')

Result:

0
1
terminating thread
Main thread exiting.
[Finished in 2.2s]
Community
  • 1
  • 1
Mikhail Gerasimov
  • 36,989
  • 16
  • 116
  • 159
  • Thank you for your answer. My original question was not about how to terminate a single thread abruptly, then I would use subprocesses. It was about how to terminate the whole process _while threads are still running_. Maybe my question was not written clearly enough. In the meantime I actually implemented something similar to your suggestion. Instead of `ev.isSet()` I would write `ev.wait(1)` and remove the call to `time.sleep()`. – Feuermurmel May 09 '17 at 11:33