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 且未 joined 的线程称为 '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