Reputation: 2592
I have the following code:
def getdata3(self, page, data, apifolder, additional):
tries = 10
for n in range(tries):
try:
except (ChunkedEncodingError, requests.exceptions.HTTPError) as e:
...
if n == tries - 1:
raise e # If arrived here - Terminate !
print ("{2} page {0} finished. Length is {1}".format(page,len(datarALL),str(datetime.now())))
return job
Main code:
with ThreadPoolExecutor(max_workers=num_of_workers) as executor:
futh = [(executor.submit(self.getdata3, page, data, apifolder,additional)) for page in pages]
for data in as_completed(futh):
datarALL.extend(data.result())
print ("Finished generateing data.")
return datarALL
This code create threads for workers. When all work is done it returns the datarALL
.
My problem:
What I want is that if one of the threads arrives here:
if n == tries - 1:
raise e # If arrived here - Terminate !
All existed threads will be terminated. No future threads will be created (terminate the for page in pages
loop) and the entire program will be terminated.
I read a few articles about the issue. I also read this Should I use Events, Semaphores, Locks, Conditions, or a combination thereof to manage safely exiting my multithreaded Python program? but the offered solutions are very complex and seem to add a lot code which I doubt I need.
I tried to do:
if n == tries - 1:
exit(1)
But when I check htop
this doesn't shut down the entire process and threads.. I have some left over that are staying there as zombies.
My Question: Is there a simple, clean solution to terminate the program with error notice?
Upvotes: 2
Views: 389
Reputation: 140178
sys.exit()
can stay stuck sometimes because it tries to exit gracefully.
Some quick & dirty solution implies the use of os._exit(1)
(1 is a possible return code indicating an error, 0 means success, you don't want to use that here. Stay in 0-255 range to avoid portability problems)
On modern systems, resource tracking happens and the program quits, killing all attached resources (file handles, threads, memory...), so it is an acceptable solution.
The downside is that it bypasses python exit/cleanup procedures, just like when you kill the python process using kill
. On OSes lacking resource tracking management (we're talking ancient history), this would result in global memory leak/file descriptors.
In your case, it doesn't matter because without this you cannot quit your application. But don't generalize it, reserve that for emergency exit procedures.
Upvotes: 3