安排一个任务在每个星期五运行,但如果完成并避免在星期五重新启动计算机,则避免运行两次;如果在星期五关闭计算机,则第二天再执行一次任务

时间:2019-03-22 11:11:23

标签: python windows scheduled-tasks schedule taskscheduler

我尝试使用各种方法来计划Python的特定任务:

  • 按自己的时间表(使用time.sleep(3600)并每小时检查一次),请参见下文
  • 尝试使用schedule之类的库

但是要拥有这个功能似乎并不容易:我希望有一个任务可以在以下两个条件下,每个星期五运行一次

  1. 如果已完成并且我在星期五重新启动计算机(或重新启动Python脚本),我不希望任务在同一天再次运行
  2. 如果计算机在星期五关闭,并且我在星期六启动计算机,则该任务应运行(因为这周它尚未运行 。)

如何使用Python很好地做到这一点?

NB:我想避免使用Windows Task Scheduler或它周围的包装器

NB2:计划任务的Python脚本在Windows启动时自动启动。


这是我尝试过的方法,但是它不是很优雅,不能满足要求2。此外,滚动自己的计划可能不是最佳选择,我正在寻找“更高级别”的东西。

try:
    with open('last.run', 'r') as f:
        lastrun = int(f.read())
except:
    lastrun = -1

while True:
        t = datetime.datetime.now()
        if t.weekday() == 4 and t.day != lastrun:
            result = doit()  # do the task
            if result:
                with open('last.run', 'w') as f:
                    f.write(str(t.day))
        print('sleeping...')
        time.sleep(3600)

1 个答案:

答案 0 :(得分:1)

由于要求2可以改写为"if the computer is off on a Friday, the task should run the next time the computer is on",因此您只需实现以下内容即可:

- Figure out the date when the task should run next time.
- Inside an endless loop:
    - if today is equal or greater than when the task should run next time:
        - run task and then (if successful) update when task should run to next Friday after today.

请注意,由于可能发生该任务应该在该月的最后一天的星期五运行,因此需要存储整个日期,而不仅是该月的某天。

要计算下星期五的日期,请查看当前评分最高的答案how-to-calculate-next-friday

try:
    with open('next.run', 'r') as f:
        nextrun = datetime.date.fromordinal(int(f.read()))
except:
    # Calculate date of next Friday (including today if today is indeed a Friday)
    today = datetime.date.today()
    nextrun = today + datetime.timedelta( (4 - today.weekday()) % 7 )

while True:
        today = datetime.date.today()
        if today >= nextrun:
            result = doit()  # do the task
            if result:
                # Calculate date of next Friday after today (the day after next Thursday)
                daysuntilnext = (3 - today.weekday()) % 7) + 1
                nextrun = today + datetime.timedelta(daysuntilnext)
                with open('next.run', 'w') as f:
                    f.write(str(nextrun.toordinal()))
                # Optional: sleep for (daysuntilnext - 1) days
        print('sleeping...')
        time.sleep(3600)