You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I bumped into a bit of a rough edge related to how concurrent.futures.Executor instances behave when they're used as context managers and there is an exception raised from the with statement body.
I had some code like this (reduced to the bare minimum):
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
futures = {
executor.submit(check_status, item): item
for item in to_check
}
for index, future in enumerate(concurrent.futures.as_completed(futures)):
print(f"{index}/{len(futures)} {future.result()}")
Now, as it happens check_status liked to raise an exception from time to time and this would be fine if the application stopped because of that but it kept going but in a weird way. What I saw was check_status kept producing logs but the print calls in the snippet above stopped being executed.
This is because of how Executor implements __exit__ – it waits for all pending futures to complete before propagating the exception:
I'm proposing changing the behavior of the context manager __exit__ to cancel futures if there is an exception:
def __exit__(self, exc_type, exc_val, exc_tb):
self.shutdown(wait=True, cancel_futures=exc_val is not None)
return False
This would allow the in-flight futures to finish but any further processing wouldn't happen and the exception would be reported in a (more) timely fashion.
cc @brianquinlan@pitrou as I saw you participate in the cancel_futures PR, if there's someone else I should ping here for visibility please let me know.
The text was updated successfully, but these errors were encountered:
I bumped into a bit of a rough edge related to how
concurrent.futures.Executor
instances behave when they're used as context managers and there is an exception raised from the with statement body.I had some code like this (reduced to the bare minimum):
Now, as it happens
check_status
liked to raise an exception from time to time and this would be fine if the application stopped because of that but it kept going but in a weird way. What I saw wascheck_status
kept producing logs but theprint
calls in the snippet above stopped being executed.This is because of how
Executor
implements__exit__
– it waits for all pending futures to complete before propagating the exception:No in my case I started with thousands of futures so it could take hours for the process to finally crash.
Since Python 3.9 the
shutdown
method has thecancel_futures
parameter (implemented in #18057): https://docs.python.org/3.9/library/concurrent.futures.html#concurrent.futures.Executor.shutdown.I'm proposing changing the behavior of the context manager
__exit__
to cancel futures if there is an exception:This would allow the in-flight futures to finish but any further processing wouldn't happen and the exception would be reported in a (more) timely fashion.
cc @brianquinlan @pitrou as I saw you participate in the
cancel_futures
PR, if there's someone else I should ping here for visibility please let me know.The text was updated successfully, but these errors were encountered: