首页 > 解决方案 > Python 在特定时间启动一个进程并在特定时间结束它

问题描述

这是一个示例 python 代码,它每 5 秒运行一个进程,直到凌晨 1 点。

def run_check():
  mythrd =threading.Timer(5.0, run_check)
  mythrd.start()
  time = datetime.now()
  domystuff()

  if time.hour == 1:
    mythrd.cancel()

run_check()

我想在特定时间启动线程。所以我改变了这段代码如下,

mythrd = None

def run_check():
  while (True):

    now = datetime.now
    if now().hour == 16 and now().minute == 30 and now().second == 30:
      mythrd.start()
      time.sleep(1)
    if mythrd.is_alive():
      domystuff()

    if datetime.now().hour == 16 and datetime.now().minute == 31:
        mythrd.cancel()

mythrd =threading.Timer(5.0, run_check)
run_check()

早些时候,我将mythrd对象保存在run_check函数中。如果我在函数内部进行初始化run_check,它将将该对象作为一个新对象。它会再次触发。所以我将mythrd函数定义为一个全局对象。但它一直在运行。我想在特定时间开始该过程并在特定时间结束它。我的代码有什么问题?

标签: pythonpython-multithreading

解决方案


这段代码有几个问题。首先,当在线程内循环并且没有命中条件时,添加睡眠以节省 CPU 使用。其次,由于线程是非确定性的,因此您无法在确切的时间戳上触发条件。例如,线程可能会在“热”时间间隔内跳过其执行,并且条件永远不会触发。

因此,您可以改为检查当前时间戳是否已通过某个时间戳(以及多少)和/或以其他方式比较时间戳。

但无论如何,在您的代码中,myrdrd 启动了一个线程函数,该函数将递归调用自身......这就是问题所在。

mythrd =threading.Timer(5.0, run_check)

进而

mythrd.start()  # will start threading.Timer(5.0, run_check)

因此,当条件now().hour == 16 and now().minute == 30 and now().second == 30触发时,线程将运行自身的另一个实例。这个实例可能运行另一个实例等等......

你的意思是实现一个触发线程,执行run_check任务,然后启动另一个线程来执行实际工作吗?

这是一个解决方案:

from threading import Thread, Timer
import time
import datetime

keep_checking = True
keep_working = True

def worker_thread():
    while keep_working:
        pass #do my stuff here and remember to use an eventual sleep

def time_checker():
    while keep_checking:
        now = datetime.now()
        if now.hour == 16 and now.minute == 30 and (
           now.second >= 30 and now.second < 31) and (
           not mythrd.isAlive()):
            mythrd.start()
        elif now.minute >= 31 and mythrd.isAlive():
            keep_working = False # and let it die instead to kill it
        else:
            time.sleep(1) # no operation

mythrd = threading.Thread(target=worker_thread)
time_checker() # might turn this into a thread as well

请记住,您需要定义线程打开和关闭的确切时间间隔。用条件覆盖所有这些情况并采取相应的行动。随着您的项目变得更加复杂,以后可能需要使用互斥锁。


推荐阅读