这是一个示例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
函数定义为全局对象。但是它一直在运行。我想在特定时间开始该过程,并在特定时间结束它。我的代码有什么问题?
答案 0 :(得分:2)
此代码存在几个问题。 首先,当在线程内部循环且没有条件发生时,请添加睡眠以节省CPU使用率。 其次,由于线程是不确定的,因此无法在确切的时间戳上触发条件。例如,线程可能会在“热”时间间隔内跳过其执行,并且该条件永远不会触发。
因此,您可以改为检查当前时间戳是否已经过某个时间戳(以及经过了多少时间)和/或比较时间戳。
但是无论如何,mythrd在代码中启动了一个线程函数,该函数将递归调用自身。...这就是问题所在。
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
请记住,您需要定义线程打开和关闭的确切时间间隔。有条件地涵盖所有这些情况,并采取相应的行动。随着您的项目变得越来越复杂,可能需要稍后使用互斥体。
答案 1 :(得分:1)
我已经为您实现了此解决方案:
from datetime import datetime as dt
import threading
import time
class test(object):
def __init__(self):
self.run_permission = False
self.start_time = [16,30,30] # Hours, Minutes, Seconds
self.end_time = [18,41,00] # Hours, Minutes, Seconds
self.timer_sched_time = 5 # seconds
threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()
while True:
time.sleep(10)
def timer_job(self, unix_time, human_time):
print "Unix time: %s Human time: %s \n" % (unix_time, human_time)
def Timer(self, delay):
while True:
try:
time_remaining = delay-time.time()%delay
time.sleep(time_remaining)
unix_time = str(int(round(time.time()*1000)))
human_time = str(dt.now())
if(self.run_permission):
self.timer_job(unix_time, human_time)
except Exception, ex:
raise ex
def check_time(self, start_execution_time, end_execution_time):
while True:
now = dt.now()
if(now.hour >= start_execution_time[0] and now.minute >= start_execution_time[1] and now.second >= start_execution_time[2]):
self.run_permission = True
if(now.hour >= end_execution_time[0] and now.minute >= end_execution_time[1] and now.second >= end_execution_time[2]):
self.run_permission = False
test()
首先,导入所需的库:
from datetime import datetime as dt
import threading
import time
创建一个名为test的类:
class test(object):
确定__init__
,当您使用test()
调用类测试时,它将在创建类测试时执行:
def __init__(self):
self.run_permission = False
self.start_time = [16,30,30] # Hours, Minutes, Seconds
self.end_time = [18,41,00] # Hours, Minutes, Seconds
self.timer_sched_time = 5 # seconds
threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()
while True:
time.sleep(10)
变量run_permission
是一个布尔值,用作检查是否可以在计时器中执行作业的标志。
start_time
变量设置check_time
例程的开始时间,该例程将run_permission
变量写入True
(如果时间很长或等于{{1}) }
start_time
变量设置end_time
例程的停止时间,该例程将check_time
变量写入False,如果该时间是主变量或等于run_permission
end_time
变量设置了计时器的延迟,该延迟是计算睡眠时间所需要的,它每5秒授予一次完美的时间执行:17.00.00-17.00.05-17.00.10-17.00 .15等等等
以下两行将启动timer_sched_time
作业和check_time
作业的线程:
Timer
这两行代码使Main线程保持运行状态,但是休眠主线程以减少资源消耗:
threading.Thread(name="time_checker", target=self.check_time, args=(self.start_time, self.end_time,)).start()
threading.Thread(name="scheduled_job", target=self.Timer, args=(self.timer_sched_time, )).start()
函数while True:
time.sleep(10)
仅以Unix格式和人类可读格式打印时间:
timer_job
要翻译Unix格式,您可以使用epoch converter website。
def timer_job(self, unix_time, human_time):
print "Unix time: %s Human time: %s \n" % (unix_time, human_time)
函数计算睡眠时间以将执行授予最佳时间,采用unix和人类格式的时间戳,如果Timer
变量将其传递给timer_job
设置为run_permission
:
True
如果遵守时间执行条件,则check_time函数使用参数def Timer(self, delay):
while True:
try:
time_remaining = delay-time.time()%delay
time.sleep(time_remaining)
unix_time = str(int(round(time.time()*1000)))
human_time = str(dt.now())
if(self.run_permission):
self.timer_job(unix_time, human_time)
except Exception, ex:
raise ex
_time和start_execution
将变量end_execution_time
设置为run_permission
或True
(因此,如果遵守小时/分钟/秒的范围):
False
如前所述,文件末尾的def check_time(self, start_execution_time, end_execution_time):
while True:
now = dt.now()
if(now.hour >= start_execution_time[0] and now.minute >= start_execution_time[1] and now.second >= start_execution_time[2]):
self.run_permission = True
if(now.hour >= end_execution_time[0] and now.minute >= end_execution_time[1] and now.second >= end_execution_time[2]):
self.run_permission = False
调用测试类,并使用test()
函数初始化程序。