While True python语句在没有cron的情况下每两周在特定日期执行一次代码?

acruukt9  于 2023-02-14  发布在  Python
关注(0)|答案(1)|浏览(93)

我如何执行代码,比如简单的打印("whatever"),每两周在特定的时间执行一次。例如,每隔一个星期一在美国东部时间下午1点打印("test")。这必须不使用cron。我意识到有很多使用crontab的解决方案。对我来说不是一个选项。这里的其他最接近的解决方案依赖于日历库,并且每周在特定的一天执行代码,但不是每两周。
有人知道一个简单易行的方法吗?
我已经试过这个Python scheduling a job starting every weekday and running every hour
我期待一种每两周运行一次任务的方法,但它不可能与该库。
编辑:
基本上是这样的,但只是每两周:

# Schedule Library imported
import schedule
import time

# Functions setup
def sudo_placement():
    print("Do something ")

schedule.every().monday.at("09:01").do(sudo_placement)
schedule.every().monday.at("09:02").do(sudo_placement)
schedule.every().monday.at("09:03").do(sudo_placement)

while True:

    schedule.run_pending()
    time.sleep(1)
lmvvr0a8

lmvvr0a81#

我们有时候使用croniter,这并不是为了满足您的需要,而是为了限制某些客户端代码的某些更新的速率,使用cron表达式指定一个"时间表"。
在您的情况下,您可以这样做:

from croniter import croniter
from datetime import datetime
import pytz

def every_other(it):
    while True:
        t = it.get_next(datetime)
        yield t
        it.get_next(datetime)

# for the example
DO_SLEEP = False  
max_runs = 5

# every other Monday 1pm ET, starting with the first Monday in January 2023
base = datetime(2023, 1, 1, tzinfo=pytz.timezone('EST5EDT'))
it = croniter('0 13 * * Mon', base)

for t in every_other(it):
    sleep_time = t.timestamp() - time.time()
    if sleep_time < 0:
        continue
    if max_runs <= 0:
        break
    max_runs -= 1
    print(f'next run: {t:%Y-%m-%d %H:%M:%S %Z}')
    if DO_SLEEP:
        time.sleep(sleep_time)
    # do whatever

打印输出(运行日期:2023年2月12日):

next run: 2023-02-13 13:00:00 EST
next run: 2023-02-27 13:00:00 EST
next run: 2023-03-13 13:00:00 EDT
next run: 2023-03-27 13:00:00 EDT
next run: 2023-04-10 13:00:00 EDT

移动双周序列

假设我们希望双周系列从2023-02-20开始,而不是从2023-02-13开始。只需更改上面的base即可。例如:

base = datetime(2023, 2, 20, tzinfo=pytz.timezone('EST5EDT'))

运行日期将为:

next run: 2023-02-20 13:00:00 EST
next run: 2023-03-06 13:00:00 EST
next run: 2023-03-20 13:00:00 EDT
next run: 2023-04-03 13:00:00 EDT
next run: 2023-04-17 13:00:00 EDT

换句话说,只需将base设置为序列中您想要的第一个星期一,即东部时间下午1点之前(或上一个星期一下午1点之后到所选开始日期下午1点之前之间的任何日期时间)。

注解

1.要按规定的时间表(每隔一个星期一的东部时间下午1点)实际运行,请设置DO_SLEEP = True
1.要运行"forever",请删除max_runs逻辑,该逻辑仅在本例中存在。
1.该程序可以被强制中断(例如,重新启动或kill -9),并在任何时候重新启动:它将继续等待系列中的下一个"另一个星期一"(锚定在2023年的第一个星期一)。
1.这可以扩展到处理多个调度和操作,但需要一堆"下一次运行时间"。相对容易做到,但超出了这个狭窄问题的范围。
1.对于非常长的等待时间(两周),我不知道单个time.sleep()是否足够准确,也许值得实现一个wait_until(timestamp),它等待越来越短的时间,直到规定的时间,然后可以使它非常准确(远低于一秒)。

相关问题