如何无限期干净地睡觉?
How to cleanly sleep indefinitely?
我的代码中启动了几个线程,我需要在脚本末尾无限期地休眠,这种休眠不会对性能造成重大影响1。
一种可能性是无限循环并短暂休眠:
while True:
time.sleep(1)
或者长时间睡眠
time.sleep(4000000)
或
import signal
signal.pause()
但是:
我没能找到 sleep 可接受的最长时间(sys.maxint
太大了)
signal.pause()
仅在 Unix 中实现
第一个 "sleep loop" 在我看来不干净(为什么是 1 秒而不是 10 或 0.1?)
是否有一种干净的 pythonic 方式可以无限期地休眠?
1 我不直接控制线程,否则我会选择 threading.Thread.join()
因为线程本身不会结束。
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()
如果您的库在您等待当前线程完成时创建新线程,则需要 while True
。
假设在 enumerate
为 运行 时没有创建线程,您可以检查 L
是否只有一个元素(主线程),如果是,则中断循环。这与带有哨兵的 Tadhg McDonald-Jensen's of using 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 未定义顺序的列表,因此如果您有多个 "main" 线程,顺序开始变得重要。一种解决方案是使用 sets,即 main_threads = {main_thread, }
和 iter(lambda : set(threading.enumerate()), main_threads)
.
如果您更喜欢 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
我的代码中启动了几个线程,我需要在脚本末尾无限期地休眠,这种休眠不会对性能造成重大影响1。
一种可能性是无限循环并短暂休眠:
while True:
time.sleep(1)
或者长时间睡眠
time.sleep(4000000)
或
import signal
signal.pause()
但是:
我没能找到 sleep 可接受的最长时间(
sys.maxint
太大了)signal.pause()
仅在 Unix 中实现第一个 "sleep loop" 在我看来不干净(为什么是 1 秒而不是 10 或 0.1?)
是否有一种干净的 pythonic 方式可以无限期地休眠?
1 我不直接控制线程,否则我会选择 threading.Thread.join()
因为线程本身不会结束。
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()
如果您的库在您等待当前线程完成时创建新线程,则需要 while True
。
假设在 enumerate
为 运行 时没有创建线程,您可以检查 L
是否只有一个元素(主线程),如果是,则中断循环。这与带有哨兵的 Tadhg McDonald-Jensen's 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 未定义顺序的列表,因此如果您有多个 "main" 线程,顺序开始变得重要。一种解决方案是使用 sets,即 main_threads = {main_thread, }
和 iter(lambda : set(threading.enumerate()), main_threads)
.
如果您更喜欢 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