Reputation: 5779
As you can see below here is a copy of my script what I've created, could someone help me improve/fix my currenttime
tasks.
Basically, during the day periodically calls test every 3 mins +- 60 seconds each periodically cycle it is supposed to do the follow tasks:
Anywhere during 23:50:00 to 01:30:00 it just idles, doing nothing other than checking the time.
from datetime import date, timedelta
from sched import scheduler
from time import time, sleep, strftime
import random
clearscreen = 0
def periodically(runtime, intsmall, intlarge, function):
global clearscreen
## Get current time
currenttime = strftime('%H:%M:%S')
## while currenttime is anywhere between 23:40 and 23:50 then...
while currenttime > '23:30:00' and currenttime < '23:40:00':
## Update time
currenttime = strftime('%H:%M:%S')
print ("""23:30:00 to 23:40:00 | %s""" % (currenttime))
sleep(1)
## If clearscreen = false then...
if clearscreen == False:
## Set clearscreen to true to enable the next part work and to disable this part until the next day.
clearscreen = True
print "changed to true"
## If currenttime is anywhere between 23:50 and 23:59 then...
while currenttime > '23:40:00' and currenttime < '23:50:00':
## Update time
currenttime = strftime('%H:%M:%S')
print ("""23:40:00 to 23:50:00 | %s""" % (currenttime))
sleep(1)
if clearscreen == True:
## clear stuff here
print "cleared"
## Change clearscreen to to stop it running
clearscreen = False
print "changed to false"
## Only allow run_periodically during 01:30 and 23:30
if clearscreen == False:
while currenttime > '23:50:00' and currenttime < '23:59:59':
## Update time
currenttime = strftime('%H:%M:%S')
print ("""23:50:00 to 23:59:59 | %s""" % (currenttime))
sleep(1)
while currenttime > '00:00:00' and currenttime < '01:30:00':
## Update time
currenttime = strftime('%H:%M:%S')
print ("""00:00:00 to 01:30:00 | %s""" % (currenttime))
sleep(1)
runtime += random.randrange(intsmall, intlarge)
s.enter(runtime, 1, function, ())
s.run()
def test():
print "test function"
while True:
periodically(180, -60, +60, test)
Any help would be much appreciated.
In regards to the loops this is what the function is supposed to be doing:
23:3x:xx - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:30:00 and 23:40:00)
23:3x:xx - clearscreen is false, setting it to true.
23:3x:xx to 23:40:00 - currenttime is updated every 1 second(s)
23:40:01 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:30:00 and 23:40:00)
23:40:01 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:40:00 and 23:50:00)
23:40:01 - clearscreen is true, doing some stuff and then changing clearscreen to false
23:40:01 to 23:50:00 - currenttime is updated every 1 second(s)
23:50:01 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:40:00 and 23:50:00)
23:50:01 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 23:50:00 and 23:59:59)
23:50:01 to 23:59:59 - currenttime is updated every 1 second(s)
00:00:00 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 23:50:00 and 23:59:59)
00:00:00 - While loop initiated as currenttime fits the while loop's conditions (time is inbetween 00:00:00 and 01:30:00)
00:00:00 and 01:30:00 - currenttime is updated every 1 second(s)
00:00:00 - While loop ended as currenttime no longer fits the while loop's conditions (time is outside of 00:00:00 and 01:30:00)
You mention that I repeatedly update currenttime, then print, then sleep. How would I get around this "problem"?
In regards to the global clearscreen
I am unsure what you mean by; "you don't have a lock on it"
I'm running Windows so signal.setitemer is a no go and also I need certain values/variables to be stored in memory for my script so scheduled tasks on windows won't be appropriate correct?
You built an example bit of code using the sched
module but it doesn't work and I am unable to work out how to get it working, plus it's also rather confusing for me. I'm still learning and it's rather confusing.
Upvotes: 1
Views: 2879
Reputation: 366103
There's no way Python can "ignore the while loops" (unless you have some other condition outside of them). But if the while loop tells Python to loop 0 times, it will do exactly that.
First, you've got this loop:
while currenttime > '23:30:00' and currenttime < '23:40:00':
… followed by this one:
while currenttime > '23:40:00' and currenttime < '23:50:00':
Think about what happens at 23:40:00. It's neither before nor after 23:40:00, so you'll skip the second loop before you even get into it.
While we're at it, two side notes on these lines:
'23:40:00' < currenttime < '23:50:00'
in Python.datetime
or time
objects instead of strings to compare times.Next, you repeatedly do this:
currenttime = strftime('%H:%M:%S')
print ("""23:40:00 to 23:50:00 | %s""" % (currenttime))
sleep(1)
This means that currenttime
is never actually the current time. It's usually a second ago. Think about what that does to your loop conditions at the edges.
As a side note, sleep(1)
isn't guaranteed to sleep exactly one second. If your computer is busy, or decides it wants to go into low-power mode, it can go significantly longer than a second. If interrupts are flying, it can go shorter than a second. Even in the best case, it'll often by off by half a clock tick in one direction or the other. So, if you need this to fire exactly 600 times, it's generally not going to do that.
Meanwhile, you've got this:
global clearscreen
Obviously there's no way anyone can ever change this in your current code, so presumably in your real code you're attempting to change it from another thread. But you don't have a lock on it. So, it's perfectly possible that you will not see a change immediately, or even ever.
Writing schedulers is a lot harder than it looks. That's why you're usually better off using an existing one. Options include:
sched
module.threading.Timer
.signal.setitemer
. Only on platforms with real signals (meaning not Windows), and possibly not appropriate on some platforms if you're using threads or fork
. Timer
(e.g., using a single timer thread with a queue of upcoming jobs, rather than a thread for each job).Since you specifically asked about sched
… There are two approaches:
enterabs
repeatedly to fill it with the day's tasks, plus one more task that runs at midnight tomorrow and does the same thing.Here's what the first one looks like:
import sched
import datetime
import time
s = sched.scheduler(time.time, time.sleep)
def dotoday():
now = datetime.date.now()
stime = now.time()
# Schedule "first" every 3 minutes from 22:00 to 22:57
if stime < datetime.time(22, 0):
stime = datetime.time(22, 0)
while stime <= datetime.time(22, 57):
s.enterabs(stime, 1, first, ())
stime += datetime.timedelta(0, 180)
# Schedule "second" every 3 minutes from 23:00 to 23:57
stime = datetime.time(23, 0)
while stime <= datetime.time(23, 57):
s.enterabs(stime, 1, second, ())
stime += datetime.timedelta(0, 180)
# Schedule "dotoday" to run tomorrow
midnight = now.replace(hour=0, minute=0, second=0)
tomorrow = midnight + datetime.timedelta(1, 0)
s.enterabs(tomorrow, 1, dotoday, ())
dotoday()
s.run()
I made this a bit more complicated than necessary, so that you can start it at 23:31:17 and it will run the first batch of tasks at 23:31:17, 23:34:17, etc. instead of waiting until 23:33:00, 23:36:00, etc.
Upvotes: 3