我有一个必须连续运行的机器人,但我希望它只在工作日的工作时间调用一个特定的功能。有人建议我用 crontab 来做,但如果我没记错的话,这是不可能的,原因有两个:
我需要将我的机器人作为 docker 镜像运行(所以在 ALpine-Lynux 中)并且 crontab 不支持 lynux os
它只允许我每隔给定的秒/分钟/小时/天重复一个动作,并且没有可能的方式“说出来”(“如果我在工作日的工作时间连续运行该动作,否则只需等待下一个工作日上午 9 点")
这就是我正在构建的,我想知道等待函数的 2 个“版本”中哪个更好,但如果您知道任何最聪明的方法,我将不胜感激
def waiting_or_not():
current_date = datetime.now(timezone('Europe/Rome'))
need_to_wait = True
if not isbday(current_date, holidays=Italy()) or current_date.hour > 18:
next_run = get_next_working_day(current_date.replace(hour=9, minute=0, second=0) + timedelta(days=1))
elif current_date.hour < 9:
next_run = current_date.replace(hour=9, minute=0, second=0)
else:
need_to_wait = False
if need_to_wait:
seconds_to_wait = (next_run - current_date).total_seconds()
# insert log
wait(next_run)
def get_next_working_day(date_):
while not isbday(date_):
date_ += timedelta(days=1)
return date_
def wait(next_run):
'''
I don't like this version at all. It seems to me ridiculous to "ask" continuously
the time. If it is friday evening after 18 and I need to wait until Monday morning,
there will be billions of useless checks.
'''
current_date = datetime.now(timezone('Europe/Rome'))
while current_date < next_run:
current_date = datetime.now(timezone('Europe/Rome'))
def wait(next_run):
'''
I read sleep function is not precise and has big problems with huge numbers of seconds
'''
current_date = datetime.now(timezone('Europe/Rome'))
time.sleep((next_run - current_date).total_seconds())
正如您所说,选项一将不断循环。 这将使您的 CPU 的一个核心占用率接近 100%, 浪费了大量的计算资源和能源。
选项二更好,实际上是实现此目的的常用方法。 根据this question,睡眠的极限大约是 大约 400 万秒,也就是大约 46 天。 如果你真的担心那个,你可以使用类似这个版本的东西:
SLEEP_LIMIT = 1000000
def wait(next_run):
seconds_till_next_run = (next_run - datetime.now(timezone('Europe/Rome'))).total_seconds()
while seconds_till_next_run > SLEEP_LIMIT:
time.sleep(SLEEP_LIMIT)
seconds_till_next_run -= SLEEP_LIMIT
if seconds_till_next_run > 0:
time.sleep(seconds_till_next_run)