Python timer script doesn't run when set to lo

2019-07-18 10:42发布

What I'm trying to do is execute a script at a certain time, and for the most part it does work when I run it a short time frame from execution, say around 10 - 15 minutes. So I would run the timer script and 10 - 15 minutes later it executes it's command.

Here is the code I'm using:

import time
import myscript
from sys import exit

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

What I want is for the script to execute everyday in the morning. When I get to my computer later in the day, I can see that the script is stuck on this process.

I've tried this on two machines, an Ubuntu 12.04 64 bit box and a Windows XP box with cygwin installed and they both show this same issue. When I leave the computers I'm only locking them, not putting them on standby. I've tried running the script and locking it, and then short unlocking it, but I can see that that isn't the issue because the script runs fine.

Also to note, when I to my computer, it seems to be running very laggy and this script seems to be taking an awful lot of CPU usage, in the range of 30 - 50%.

What else am I missing, or is this not the ideal way to go about it?

2条回答
疯言疯语
2楼-- · 2019-07-18 10:57

Update: If you need to run it exactly once at the first opportunity after 7:15am:

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()

It runs main at 7:15am or shortly after the computer has awoken if it is asleep at 7:15am.


As other have said an existing solution such as cron, Windows task scheduler might be preferable for running your script at specified times.

To avoid the explicit busy loop you could use 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)

It calls the main function everyday at 7:15 in local time.

It skips the call if the previous one is not complete yet or your computer is suspended at 7:15. It might skip DST transition day.

It should work If the system clock is set back/forward between the calls.

To handle more complex scheduling specifications you could use the crontab syntax in Python, example.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-07-18 11:01

Having no sleep in there explains why your system freaks out. It is spinning as fast as your cpu can go.

If you are just experimenting with a wrapping script that will run a function at a specific time, you can just do this:

from datetime import datetime
import time

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

But here is a big problem to think about. What happens if foo() takes a long time or hangs from its own operation?

What might have been happening in your case is that your sleep (being set to 60 seconds) might have really missed that minute window. You would have to sleep for smaller increments to make sure you check the minute multiple times.

Aside from this, use a cron job. It is meant to do scheduled tasks. cron will exist in the cygwin shell that you mentioned you are using anyways. Refer here for setting up a crontab on windows

查看更多
登录 后发表回答