2

我想要做的是在某个时间执行一个脚本,并且在大多数情况下,当我在执行后的短时间内运行它时,它确实有效,比如大约 10 到 15 分钟。所以我会运行计时器脚本,10 - 15 分钟后它会执行它的命令。

这是我正在使用的代码:

import time
import myscript
from sys import exit

while 1:
        if time.strftime("%H") == "7" and time.strftime("%M") == "15":
                myscript.main()
                exit()

我想要的是脚本每天早上执行。当我在当天晚些时候到达我的电脑时,我可以看到脚本卡在这个过程中。

我在两台机器上试过这个,一个 Ubuntu 12.04 64 位机器和一个安装了 cygwin 的 Windows XP 机器,它们都显示了同样的问题。当我离开电脑时,我只是锁定它们,而不是让它们处于待机状态。我尝试运行脚本并锁定它,然后短暂解锁它,但我可以看到这不是问题,因为脚本运行良好。

另外需要注意的是,当我使用我的计算机时,它似乎运行得很慢,而且这个脚本似乎占用了大量的 CPU 使用率,在 30 - 50% 的范围内。

我还缺少什么,或者这不是解决问题的理想方法?

4

2 回答 2

2

在那里没有睡觉可以解释为什么你的系统会崩溃。它的旋转速度与您的 cpu 一样快。

如果您只是在试验将在特定时间运行函数的包装脚本,您可以这样做:

from datetime import datetime
import time

while True:
    now = datetime.now()
    if now.hour == 7 and now.minute == 15:
        foo()
    time.sleep(10)

但这里有一个大问题需要考虑。如果foo()需要很长时间或挂起自己的操作会发生什么?

在您的情况下可能发生的情况是您的睡眠(设置为 60 秒)可能真的错过了那个分钟窗口。您必须以较小的增量睡眠,以确保您多次检查分钟。

除此之外,使用 cron 作业。它旨在执行计划任务。cron 将存在于您提到的您正在使用的 cygwin shell 中。请参阅此处以在 Windows 上设置 crontab

于 2012-08-17T22:30:42.670 回答
1

更新:如果您需要在早上 7 点 15 分之后的第一次机会运行一次:

now = datetime.now()
dt = now.replace(hour=7, minute=15) #note: ignore seconds, microseconds
if dt < now:
   dt += timedelta(days=1) #note: might miss by an hour on DST transition day
assert dt >= now
delay = (dt - datetime.now()).total_seconds()
Timer(delay, myscript.main).start()

它在main早上 7 点 15 分运行,或者如果计算机在早上 7 点 15 分处于睡眠状态,则在计算机唤醒后不久运行。


正如其他人所说的现有解决方案(例如 cron),Windows 任务调度程序可能更适合在指定时间运行您的脚本。

为了避免显式繁忙循环,您可以使用threading.Timer().

#!/usr/bin/env python
from datetime  import datetime, timedelta
from threading import Timer

import myscript

def run_at(dt, func, step=timedelta(days=1), tolerance=timedelta(minutes=1)):
    if abs(dt - datetime.now()) < tolerance:
       func() # don't schedule if it raises an exception

    now = datetime.now()
    while dt < now:
        dt += step

    delay = (dt - datetime.now()).total_seconds()
    Timer(delay, run_at, [dt, func]).start()

dt = datetime.now().replace(hour=7, minute=15)
run_at(dt, myscript.main)

它在当地时间每天 7:15 调用 main 函数。

如果前一个呼叫尚未完成或您的计算机在 7:15 暂停,它将跳过呼叫。它可能会跳过 DST 过渡日。

如果系统时钟在呼叫之间向后/向前设置,它应该可以工作。

要处理更复杂的调度规范,您可以使用 Python 中的 crontab 语法,例如.

于 2012-08-18T02:04:03.340 回答