简体   繁体   English

如何无限期清洁睡眠?

[英]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 . 我的代码中启动了几个线程,我需要在脚本结尾无限期地休眠,而这种休眠不会对性能产生重大影响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) 我没有找到睡眠可以接受的最大时间( sys.maxint太大)

  • signal.pause() is implemented in Unix only signal.pause()仅在Unix中实现

  • and the first "sleep loop" does not look clean to me (why 1 second and not 10, or 0.1?) 而第一个“睡眠循环”对我来说看起来并不干净(为什么是1秒而不是10秒或0.1?)

Is there a clean, pythonic way to sleep indefinitely? 有没有一种干净的,Python式的无限期睡眠方式?


1 I do not control the threads directly, otherwise I would have gone for threading.Thread.join() as the threads themselves will not end. 1我不直接控制线程,否则我会去使用threading.Thread.join()因为线程本身不会结束。

threading.enumerate gives you the list of all running threads including the main one, so you could do this: threading.enumerate为您提供了所有正在运行的线程(包括主线程)的列表,因此您可以执行以下操作:

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. 如果您的库在等待当前线程完成时创建新线程,则需要使用while True

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. 假设在enumerate运行时没有创建线程,则可以检查L是否只有一个元素(主线程),如果有,则中断循环。 This combined with Tadhg McDonald-Jensen 's suggestion of using iter with a sentinel, results in: 结合Tadhg McDonald-Jensen建议 ,将iter与前哨一起使用,结果是:

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. enumerate以未定义的顺序返回列表,因此,如果您有多个“主”线程,顺序就变得很重要。 A solution would be to use sets , ie main_threads = {main_thread, } and iter(lambda : set(threading.enumerate()), main_threads) . 一种解决方案是使用集合 ,即main_threads = {main_thread, }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: 如果您更喜欢请求宽恕而不是许可的EAFP方法,并且在脚本结束时启动了所有线程,那么您也可以这样做:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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