Python 在不阻塞其他进程的情况下休眠
Python sleep without blocking other processes
我每小时 运行 一个 python 脚本,我一直在 while 循环中使用 time.sleep(3600)
。它似乎可以按需工作,但我担心它会阻止新任务。我对此的研究似乎是它只会阻塞当前线程,但我想 100% 确定。虽然每小时的工作不应超过 15 分钟,但如果超过 15 分钟或挂起,我不希望它阻止下一个开始的工作。我是这样做的:
import threading
import time
def long_hourly_job():
# do some long task
pass
if __name__ == "__main__":
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
time.sleep(3600)
这够了吗?
此外,我使用 time.sleep
来完成这个每小时工作而不是 cron 工作的原因是我想在代码中做所有事情来使 dockerization 更干净。
代码会起作用(即:sleep
只会阻塞调用线程),但您应该注意一些问题。其中一些已在评论中说明,例如线程之间时间重叠的可能性。主要问题是您的代码正在慢慢泄漏资源。创建线程后,OS 甚至在线程完成 运行ning 后仍保留一些数据结构。这是必要的,例如,为了保持线程的退出状态直到线程的创建者需要它。清除这些结构(概念上等同于关闭文件)的函数称为 join
。已完成 运行ning 且未 join
ed 的线程称为 'zombie thread'。这些结构所需的内存量非常小,对于任何合理数量的可用 RAM,您的程序应该 运行 几个世纪。尽管如此,加入您创建的所有线程是一个很好的做法。一个简单的方法(如果您知道 3600 秒足以让线程完成)是:
if __name__ == "__main__":
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
thr.join(3600) # wait at most 3600 s for the thread to finish
if thr.isAlive(): # join does not return useful information
print("Ooops: the last job did not finish on time")
如果您认为有时 3600 秒可能不足以让线程完成,则更好的方法是:
if __name__ == "__main__":
previous = []
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
previous.append(thr)
time.sleep(3600)
for i in reversed(range(len(previous))):
t = previous[i]
t.join(0)
if t.isAlive():
print("Ooops: thread still running")
else:
print("Thread finished")
previous.remove(t)
我知道 print
语句没有意义:请改用 logging
。
我每小时 运行 一个 python 脚本,我一直在 while 循环中使用 time.sleep(3600)
。它似乎可以按需工作,但我担心它会阻止新任务。我对此的研究似乎是它只会阻塞当前线程,但我想 100% 确定。虽然每小时的工作不应超过 15 分钟,但如果超过 15 分钟或挂起,我不希望它阻止下一个开始的工作。我是这样做的:
import threading
import time
def long_hourly_job():
# do some long task
pass
if __name__ == "__main__":
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
time.sleep(3600)
这够了吗?
此外,我使用 time.sleep
来完成这个每小时工作而不是 cron 工作的原因是我想在代码中做所有事情来使 dockerization 更干净。
代码会起作用(即:sleep
只会阻塞调用线程),但您应该注意一些问题。其中一些已在评论中说明,例如线程之间时间重叠的可能性。主要问题是您的代码正在慢慢泄漏资源。创建线程后,OS 甚至在线程完成 运行ning 后仍保留一些数据结构。这是必要的,例如,为了保持线程的退出状态直到线程的创建者需要它。清除这些结构(概念上等同于关闭文件)的函数称为 join
。已完成 运行ning 且未 join
ed 的线程称为 'zombie thread'。这些结构所需的内存量非常小,对于任何合理数量的可用 RAM,您的程序应该 运行 几个世纪。尽管如此,加入您创建的所有线程是一个很好的做法。一个简单的方法(如果您知道 3600 秒足以让线程完成)是:
if __name__ == "__main__":
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
thr.join(3600) # wait at most 3600 s for the thread to finish
if thr.isAlive(): # join does not return useful information
print("Ooops: the last job did not finish on time")
如果您认为有时 3600 秒可能不足以让线程完成,则更好的方法是:
if __name__ == "__main__":
previous = []
while True:
thr = threading.Thread(target=long_hourly_job)
thr.start()
previous.append(thr)
time.sleep(3600)
for i in reversed(range(len(previous))):
t = previous[i]
t.join(0)
if t.isAlive():
print("Ooops: thread still running")
else:
print("Thread finished")
previous.remove(t)
我知道 print
语句没有意义:请改用 logging
。