|from concurrent.futures import ThreadPoolExecutor, as_completed|
|print('Removing file %s' % path)|
|time.sleep(10) # Pretending that I'm removing the file...|
|print('%s is removed' % path)|
|not_graceful = sys.argv[1:] and sys.argv == '--not-graceful'|
|print('I will _not_ be shut down gracefully...')|
|print('I will be shut down gracefully... (default behavior)')|
|with ThreadPoolExecutor(1) as executor:|
|futures = [executor.submit(remove_file, path) for path in 'abcd']|
|for future in as_completed(futures):|
A graceful shutdown when you hitting Ctrl-C will go on removing more files.
A non-graceful shutdown won't.
A very late reply to @gaborbernat: The thread executor module joins the executor threads at two levels. One is in the shutdown function. I disabled it with
The second join point is the atexit callback. I think it can only be disabled with
A side note: I haven't dug into the revision history, but it is interesting that the executor module tries very hard to join the threads, and yet it sets all threads to be daemons.
In Python >= 3.7 the following part will return an error:
For example, in my script
In order to workaround this issue you can add the following line to the importing part of your program: