Python:每天随机执行一个函数次数
Python: execute a function a random number of times per day
我想在设定的时间段内每天随机执行一次函数。这是我目前所拥有的:
def get_epochtime(dt=datetime.now()):
EPOCH = datetime(1970, 1, 1)
return (dt - EPOCH).total_seconds()
def get_todays_run_schedule(runs_per_day, run_between):
now = datetime.now()
window_start = now.replace(hour=run_between[0])
window_end = now.replace(hour=run_between[1])
the_schedule = [ get_epochtime(radar.random_datetime(start=window_start, stop=window_end)) for t in range(randint(runs_per_day[0], runs_per_day[1])) ]
the_schedule.sort()
print("Today I will run %s times" % len(the_schedule))
for run_at in the_schedule:
print("I will run at " + time.strftime("%Y-%m-%d %H:%M", time.localtime(run_at)))
return the_schedule
# we will run between 2 and 4 times per day between the hours of 10 AM and 5 PM.
schedule = get_todays_run_schedule((2, 4), (10, 17))
while(True):
now = datetime.now()
nowsecs = get_epochtime(now)
if now.hour == 0 and now.minute == 0 and now.second == 0:
schedule = get_todays_run_schedule()
if nowsecs in schedule:
execute_my_function
sleep(1)
基本上这个想法是,在午夜和首先 运行,我们想出了一个 运行 时间表,它是一个纪元时间列表,其长度在两个提供的整数之间。我们每秒检查一次时间,如果当前时间在 运行 次列表内,我们将执行我们的函数。终于睡到下一秒了
但是,它根本不起作用。我怀疑这可能是因为我的日期时间对象以某种方式包含微秒,这会影响比较,但这可能是因为我不了解 python.
中日期时间比较的性质。
微秒对你来说确实是个问题——你列表中的对象和 now
都有微秒,运行 一个循环只有 once/second,这些 now
中的任何一个与事件时间戳完全匹配的可能性很小。
但即使您通过将 now
和列表中的值都截断为秒数来修复该问题,仍然无法解决问题,只会使其成为一个更难调试的间歇性问题.考虑一下如果您在 15:25:26 有一个事件并在 15:25:25.907 开始循环会发生什么。您将其截断为 15:25:25,查找它,它不存在。然后你睡了大约一秒钟,然后调用 now()
,然后你得到,比方说,15:25:27.033。您将其截断为 15:25:27,查找它,但它也不存在。
既然您已经对列表进行了排序,那么您可以做一些更简单的事情,我将在下面进行演示。但首先:当我们讨论它时, datetime
对象的全部意义在于它们可以直接进行时间比较、算术等,所以你不需要像你的 get_epochtime
.
yesterday = datetime.today() - datetime.timedelta(days=1)
while True:
now = datetime.now()
if now.date() > yesterday:
schedule = get_todays_run_schedule()
yesterday = now.date()
while schedule and now >= schedule[0]:
del schedule[0]
execute_my_function
sleep(1)
(显然,您还需要将 get_todays_run_schedule
更改为 return datetime
对象列表而不是浮点数列表来执行此操作,但您应该能够弄清楚。)
另外,请注意,通过这种方式,我们始终知道下一个事件之前的时间,因此我们不需要循环 sleep(1)
并在计算机使用电池时保持每秒唤醒一次。您可以在有下一个事件时 sleep(schedule[0] - now)
,或者在没有事件时睡到午夜。或者,也许更简单,当 schedule
变空时生成明天的时间表,然后一直睡到 schedule[0]
.
其实仔细想想,应该能想出如何把它变成这种形式的循环:
while True:
schedule = make_today_or_tomorrow_schedule()
for event in schedule:
while datetime.now() < event:
sleep(event - datetime.now())
execute_my_function
我想在设定的时间段内每天随机执行一次函数。这是我目前所拥有的:
def get_epochtime(dt=datetime.now()):
EPOCH = datetime(1970, 1, 1)
return (dt - EPOCH).total_seconds()
def get_todays_run_schedule(runs_per_day, run_between):
now = datetime.now()
window_start = now.replace(hour=run_between[0])
window_end = now.replace(hour=run_between[1])
the_schedule = [ get_epochtime(radar.random_datetime(start=window_start, stop=window_end)) for t in range(randint(runs_per_day[0], runs_per_day[1])) ]
the_schedule.sort()
print("Today I will run %s times" % len(the_schedule))
for run_at in the_schedule:
print("I will run at " + time.strftime("%Y-%m-%d %H:%M", time.localtime(run_at)))
return the_schedule
# we will run between 2 and 4 times per day between the hours of 10 AM and 5 PM.
schedule = get_todays_run_schedule((2, 4), (10, 17))
while(True):
now = datetime.now()
nowsecs = get_epochtime(now)
if now.hour == 0 and now.minute == 0 and now.second == 0:
schedule = get_todays_run_schedule()
if nowsecs in schedule:
execute_my_function
sleep(1)
基本上这个想法是,在午夜和首先 运行,我们想出了一个 运行 时间表,它是一个纪元时间列表,其长度在两个提供的整数之间。我们每秒检查一次时间,如果当前时间在 运行 次列表内,我们将执行我们的函数。终于睡到下一秒了
但是,它根本不起作用。我怀疑这可能是因为我的日期时间对象以某种方式包含微秒,这会影响比较,但这可能是因为我不了解 python.
中日期时间比较的性质。微秒对你来说确实是个问题——你列表中的对象和 now
都有微秒,运行 一个循环只有 once/second,这些 now
中的任何一个与事件时间戳完全匹配的可能性很小。
但即使您通过将 now
和列表中的值都截断为秒数来修复该问题,仍然无法解决问题,只会使其成为一个更难调试的间歇性问题.考虑一下如果您在 15:25:26 有一个事件并在 15:25:25.907 开始循环会发生什么。您将其截断为 15:25:25,查找它,它不存在。然后你睡了大约一秒钟,然后调用 now()
,然后你得到,比方说,15:25:27.033。您将其截断为 15:25:27,查找它,但它也不存在。
既然您已经对列表进行了排序,那么您可以做一些更简单的事情,我将在下面进行演示。但首先:当我们讨论它时, datetime
对象的全部意义在于它们可以直接进行时间比较、算术等,所以你不需要像你的 get_epochtime
.
yesterday = datetime.today() - datetime.timedelta(days=1)
while True:
now = datetime.now()
if now.date() > yesterday:
schedule = get_todays_run_schedule()
yesterday = now.date()
while schedule and now >= schedule[0]:
del schedule[0]
execute_my_function
sleep(1)
(显然,您还需要将 get_todays_run_schedule
更改为 return datetime
对象列表而不是浮点数列表来执行此操作,但您应该能够弄清楚。)
另外,请注意,通过这种方式,我们始终知道下一个事件之前的时间,因此我们不需要循环 sleep(1)
并在计算机使用电池时保持每秒唤醒一次。您可以在有下一个事件时 sleep(schedule[0] - now)
,或者在没有事件时睡到午夜。或者,也许更简单,当 schedule
变空时生成明天的时间表,然后一直睡到 schedule[0]
.
其实仔细想想,应该能想出如何把它变成这种形式的循环:
while True:
schedule = make_today_or_tomorrow_schedule()
for event in schedule:
while datetime.now() < event:
sleep(event - datetime.now())
execute_my_function