简体   繁体   中英

How to cleanly sleep indefinitely?

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 performance 1 .

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.

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 , ie 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM