Reputation: 29977
A few threads are started in my code and I need at the end of the script to sleep indefinitely, without this sleep being a major hit on the performance1.
One possibility can be to loop indefinitely with a short sleep:
while True:
time.sleep(1)
or sleep for a long time
time.sleep(4000000)
or
import signal
signal.pause()
But:
I did not manage to find the largest time sleep would accept (sys.maxint
is too large)
signal.pause()
is implemented in Unix only
and the first "sleep loop" does not look clean to me (why 1 second and not 10, or 0.1?)
Is there a clean, pythonic way to sleep indefinitely?
1 I do not control the threads directly, otherwise I would have gone for threading.Thread.join()
as the threads themselves will not end.
Upvotes: 5
Views: 3427
Reputation: 20870
threading.enumerate
gives you the list of all running threads including the main one, so you could do this:
main_thread = threading.main_thread()
while True:
L = threading.enumerate()
L.remove(main_thread) # or avoid it in the for loop
for t in L:
t.join()
The while True
is needed in case your library creates new threads while you wait for the current ones to finish.
Assuming that no threads are created while enumerate
is running, you can check if L
has only one element (the main thread) and if so, break the loop. This combined with Tadhg McDonald-Jensen's suggestion of using iter
with a sentinel, results in:
main_thread = threading.main_thread()
main_threads = [main_thread, ] # WARN: can't have more than one thread here
for threads in iter(threading.enumerate, main_threads):
for t in threads:
if t == main_thread:
continue
t.join()
enumerate
returns a list in undefined order, so if you have more than one "main" thread, order starts to matter. A solution would be to use sets, i.e. main_threads = {main_thread, }
and iter(lambda : set(threading.enumerate()), main_threads)
.
If you prefer the EAFP approach of asking for forgiveness instead of permission and all your threads are started when you reach the end of your script, you can also do this:
for thread in threading.enumerate():
try:
thread.join()
except RuntimeError:
# trying to join the main thread, which would create a deadlock (see https://docs.python.org/3/library/threading.html#threading.Thread.join for details)
pass
Upvotes: 6