To schedule tasks and stop tasks after some time - python

Well, I am making this program which will click a link sent on zoom and close zoom at the end of meeting
This is the code
import pyautogui
import time
import pause
import datetime
import schedule
YEAR = 2020
MONTH = 11
DATE = 6
HOUR = 10
MINUTES = 1
SECONDS = 00
now = datetime.datetime.now()
EndTime = now.replace(hour=HOUR, minute=MINUTES, second=SECONDS, microsecond=0)
JustBefore= now.replace(hour=HOUR, minute=MINUTES-1, second=SECONDS, microsecond=0)
def leave_the_meeting():
pyautogui.click(1198, 1072)
time.sleep(3)
pyautogui.click(1443, 998)
time.sleep(1)
pyautogui.click(1398, 933)
def click_the_attendance_link():
pyautogui.click(1665, 674)
time.sleep(9)
I want click_the_attendance_link() to keep functioning over and over again until JustBefore and then stop.
and then I want leave_the_meeting() to start functioning for just one time at EndTime.
What code should I add?

How about this:
def keep_click_attendance_link():
while datetime.datetime.now() < JustBefore:
click_attendance_link()
# Sleep for 60 secs before trying again
time.sleep(60)
while datetime.datetime.now() < Endtime:
# Sleep for 1 sec intervals:
time.sleep(1)
# eventually Leave the meeting at Endtime
leave_the_meeting()

Related

Use the schedule library to run a job once tomorrow

schedule.wednesday.at("13:15").do(job)
With this code I can run fuction on wednesday 13:15. But I want to make action like, "run function next day morning '10:00' " How can do this?
Wrap job to return schedule.CancelJob such that it runs only once. Then schedule it to run every day at 10:00.
def job_once():
job()
return schedule.CancelJob
schedule.every().day.at('10:00').do(job_once)
Caveat: if the current time is before 10:00, then the job will run this day at 10:00. There's no way to define an initial delay in the schedule library - but we could get the name of the next day and schedule on this day.
import datetime
tomorrow = (datetime.datetime.now() + datetime.timedelta(days=1)).strftime('%A').lower()
getattr(schedule.every(), tomorrow).at('10:00').do(job_once)
Python contains a simple library called sched:
import sched, time
def functionYouWantToRun():
...
s = sched.scheduler(time.localtime, time.sleep)
s.enterabs(time.strptime('[three character day] [three character month] [day of month] [time (hh:mm:ss)] [year]')
s.run()
def job_that_executes_once():
# Do some work that only needs to happen once...
return schedule.CancelJob
if __name__ == "__main__":
from datetime import datetime, timedelta
import schedule
schedule.every().day.at("10:00").do(job_that_executes_once)
I was going to go with time offset, but then realised the above is easier. That will run it the next day.
If you need to run several days in the future, then you are back to datetime offsets:
x=datetime.today()
y = x.replace(day=x.day, hour=10, minute=0, second=0, microsecond=0) +
timedelta(days=1)
yDay = y.strftime('%A')

Run Function at Given DateTime [duplicate]

How can I run a function in Python, at a given time?
For example:
run_it_at(func, '2012-07-17 15:50:00')
and it will run the function func at 2012-07-17 15:50:00.
I tried the sched.scheduler, but it didn't start my function.
import time as time_module
scheduler = sched.scheduler(time_module.time, time_module.sleep)
t = time_module.strptime('2012-07-17 15:50:00', '%Y-%m-%d %H:%M:%S')
t = time_module.mktime(t)
scheduler_e = scheduler.enterabs(t, 1, self.update, ())
What can I do?
Reading the docs from http://docs.python.org/py3k/library/sched.html:
Going from that we need to work out a delay (in seconds)...
from datetime import datetime
now = datetime.now()
Then use datetime.strptime to parse '2012-07-17 15:50:00' (I'll leave the format string to you)
# I'm just creating a datetime in 3 hours... (you'd use output from above)
from datetime import timedelta
run_at = now + timedelta(hours=3)
delay = (run_at - now).total_seconds()
You can then use delay to pass into a threading.Timer instance, eg:
threading.Timer(delay, self.update).start()
Take a look at the Advanced Python Scheduler, APScheduler: http://packages.python.org/APScheduler/index.html
They have an example for just this usecase:
http://packages.python.org/APScheduler/dateschedule.html
from datetime import date
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.start()
# Define the function that is to be executed
def my_job(text):
print text
# The job will be executed on November 6th, 2009
exec_date = date(2009, 11, 6)
# Store the job in a variable in case we want to cancel it
job = sched.add_date_job(my_job, exec_date, ['text'])
Might be worth installing this library: https://pypi.python.org/pypi/schedule, basically helps do everything you just described. Here's an example:
import schedule
import time
def job():
print("I'm working...")
schedule.every(10).minutes.do(job)
schedule.every().hour.do(job)
schedule.every().day.at("10:30").do(job)
schedule.every().monday.do(job)
schedule.every().wednesday.at("13:15").do(job)
while True:
schedule.run_pending()
time.sleep(1)
Here's an update to stephenbez' answer for version 3.5 of APScheduler using Python 2.7:
import os, time
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
def tick(text):
print(text + '! The time is: %s' % datetime.now())
scheduler = BackgroundScheduler()
dd = datetime.now() + timedelta(seconds=3)
scheduler.add_job(tick, 'date',run_date=dd, args=['TICK'])
dd = datetime.now() + timedelta(seconds=6)
scheduler.add_job(tick, 'date',run_date=dd, kwargs={'text':'TOCK'})
scheduler.start()
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
# This is here to simulate application activity (which keeps the main thread alive).
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
# Not strictly necessary if daemonic mode is enabled but should be done if possible
scheduler.shutdown()
I've confirmed the code in the opening post works, just lacking scheduler.run(). Tested and it runs the scheduled event. So that is another valid answer.
>>> import sched
>>> import time as time_module
>>> def myfunc(): print("Working")
...
>>> scheduler = sched.scheduler(time_module.time, time_module.sleep)
>>> t = time_module.strptime('2020-01-11 13:36:00', '%Y-%m-%d %H:%M:%S')
>>> t = time_module.mktime(t)
>>> scheduler_e = scheduler.enterabs(t, 1, myfunc, ())
>>> scheduler.run()
Working
>>>
I ran into the same issue: I could not get absolute time events registered with sched.enterabs to be recognized by sched.run. sched.enter worked for me if I calculated a delay, but is awkward to use since I want jobs to run at specific times of day in particular time zones.
In my case, I found that the issue was that the default timefunc in the sched.scheduler initializer is not time.time (as in the example), but rather is time.monotonic. time.monotonic does not make any sense for "absolute" time schedules as, from the docs, "The reference point of the returned value is undefined, so that only the difference between the results of consecutive calls is valid."
The solution for me was to initialize the scheduler as
scheduler = sched.scheduler(time.time, time.sleep)
It is unclear whether your time_module.time is actually time.time or time.monotonic, but it works fine when I initialize it properly.
dateSTR = datetime.datetime.now().strftime("%H:%M:%S" )
if dateSTR == ("20:32:10"):
#do function
print(dateSTR)
else:
# do something useful till this time
time.sleep(1)
pass
Just looking for a Time of Day / Date event trigger:
as long as the date "string" is tied to an updated "time" string, it works as a simple TOD function. You can extend the string out to a date and time.
whether its lexicographical ordering or chronological order comparison,
as long as the string represents a point in time, the string will too.
someone kindly offered this link:
String Comparison Technique Used by Python
had a really hard time getting these answers to work how i needed it to,
but i got this working and its accurate to .01 seconds
from apscheduler.schedulers.background import BackgroundScheduler
sched = BackgroundScheduler()
sched.start()
def myjob():
print('job 1 done at: ' + str(dt.now())[:-3])
dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2000)
job = sched.add_job(myjob, 'date', run_date=Future)
tested accuracy of timing with this code:
at first i did 2 second and 5 second delay, but wanted to test it with a more accurate measurement so i tried again with 2.55 second delay and 5.55 second delay
dt = datetime.datetime
Future = dt.now() + datetime.timedelta(milliseconds=2550)
Future2 = dt.now() + datetime.timedelta(milliseconds=5550)
def myjob1():
print('job 1 done at: ' + str(dt.now())[:-3])
def myjob2():
print('job 2 done at: ' + str(dt.now())[:-3])
print(' current time: ' + str(dt.now())[:-3])
print(' do job 1 at: ' + str(Future)[:-3] + '''
do job 2 at: ''' + str(Future2)[:-3])
job = sched.add_job(myjob1, 'date', run_date=Future)
job2 = sched.add_job(myjob2, 'date', run_date=Future2)
and got these results:
current time: 2020-12-10 19:50:44.632
do job 1 at: 2020-12-10 19:50:47.182
do job 2 at: 2020-12-10 19:50:50.182
job 1 done at: 2020-12-10 19:50:47.184
job 2 done at: 2020-12-10 19:50:50.183
accurate to .002 of a second with 1 test
but i did run a lot of tests and accuracy ranged from .002 to .011
never going under the 2.55 or 5.55 second delay
#everytime you print action_now it will check your current time and tell you should be done
import datetime
current_time = datetime.datetime.now()
current_time.hour
schedule = {
'8':'prep',
'9':'Note review',
'10':'code',
'11':'15 min teabreak ',
'12':'code',
'13':'Lunch Break',
'14':'Test',
'15':'Talk',
'16':'30 min for code ',
'17':'Free',
'18':'Help ',
'19':'watever',
'20':'watever',
'21':'watever',
'22':'watever'
}
action_now = schedule[str(current_time.hour)]

Read time(s) from .txt file, then countdown to that time

I have a text file called sorted_passes.txt with the following:
NOAA18 23/08/2020 10:56:46 Max Elev: 67
NOAA19 23/08/2020 19:08:02 Max Elev: 74
NOAA15 23/08/2020 20:12:44 Max Elev: 87
NOAA18 23/08/2020 22:19:47 Max Elev: 90
I would like to have a timer either do one of the following:
Count down to the next time in the .txt file and then after that time, move to the next time, again, counting down.
Count down to each time in the .txt file
My plan is to eventually have the countdown timer(s) display via a MAX7219 led board connected to raspberry pi.
So far, I have this python code:
# calculate time until next pass
from datetime import datetime
futuredate = datetime.strptime('10:56:46', '%H:%M:%S')
nowdate = datetime.now()
count = int((futuredate-nowdate).total_seconds())
days = count//86400
hours = (count-days*86400)//3600
minutes = (count-days*86400-hours*3600)//60
seconds = count-days*86400-hours*3600-minutes*60
print("Next Pass: {}h:{}m:{}s".format(hours, minutes, seconds))
This should get you started:
from datetime import datetime
from time import sleep
def compare(event):
"""Return True if it's counting down, false if the time already passed"""
now = datetime.now()
if now <= event:
diff = event - now
print("Countdown: {}".format(diff))
return True
else:
return False
def extract_timestamp(line):
"""Extract datetime from string:
NOAA18 23/08/2020 10:56:46 Max Elev: 67
"""
time_stamp = line[7:][:-14]
time_event = datetime.strptime(time_stamp, '%d/%m/%Y %H:%M:%S')
return time_event
def open_file():
with open('sorted_passes.txt', 'r') as f:
return f.readlines()
data = open_file()
# iterate through the lines of the file
for line in data:
ts = extract_timestamp(line)
while compare(ts):
sleep(1)
else:
print("Next event")
continue
print("Finished")
This will print a countdown statement with how long it takes, sleeps a second. Or it will go to the next event until all lines are checked.
You need to make sure the file dates are incremental (e.g. a new line is always later than the earlier lines).
Example output (I manually changed the date in the last line):
Next event
Next event
Next event
Countdown: 0:00:03.531014
Countdown: 0:00:02.526724
Countdown: 0:00:01.524277
Countdown: 0:00:00.518995
Finished

User-specific date countdown

I am new here and I was hoping someone could help me out with a project I'm attempting to create. Using Python I would like to make a countdown clock from user-specific information that, when getting a month day and year, would finish by printing an active countdown clock for that specific date. Is this possible? If so, how?
Thanks in advance.
-Anthony
The code below can be a start. The function date_countdown takes in a date string and a date format corresponding to the date string, and outputs a countdown to the terminal.
countdown.py
import datetime
def date_countdown(future_datetime, date_format):
print("Countdown for {}:".format(future_datetime))
seconds_left = -1
while seconds_left:
cur = datetime.datetime.now()
fut = datetime.datetime.strptime(future_datetime, date_format)
left = fut - cur
print(
"{0: >3d} days, {1:0>2d}:{2:0>2d}:{3:0>2d}".format(
left.days, # days
left.seconds // 3600, # hours
(left.seconds // 60) % 60, # minutes
(left.seconds % 60) # seconds
),
end='\r')
time.sleep(1)
seconds_left = left.total_seconds()
print('Done!')
date_countdown('2018-12-25', '%Y-%m-%d')
Output:
Countdown for 2018-12-25:
27 days, 04:15:40

how to write an if statement in python comparing time to a value

I'm trying to write a simple code in python to turn on a led light during certain hours of the day, then turn it off for the rest of the time. I tried to indicate the time frames in the if statement but everytime I run this code, only the "else" portion of the if statement works. Am I not allowed to compare my time format of HHMM to a flat value of 0745? If not how can I get the led to stay on from midnight to 7:45 in the morning? Any help or direction would be greatly appreciated!
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
print (time.strftime("%H%M"))
while True:
if time.strftime("%H%M") <= 0745:
GPIO.output(3,1)
else:
GPIO.output(3,0)
Try to use datetime.
import datetime
while True:
time = datetime.datetime.now()
morning = time.replace(hour=7, minute=45, second=0, microsecond=0)
if time <= morning:
print("turn on")
else:
print("turn off")
Python has a datetime module that provides data types to work with dates and times.
You could write the code from your question like this:
import datetime
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
while True:
if datetime.datetime.now() <= datetime.datetime.combine(
datetime.date.today(),
datetime.time(7, 45)
):
GPIO.output(3,1)
else:
GPIO.output(3,0)
However, this still has the problem that the program will constantly spin in the while loop and suck up as much CPU cycles as it can get.
You could do something like this instead:
import time
import datetime
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
schedule = [
(datetime.time(0, 0), 0),
(datetime.time(7, 45), 1),
(datetime.time(18, 0), 0)
]
def switchLight():
"""
Switch the light to the proper state according to the schedule.
Return the next time the light needs to be switched.
"""
today = datetime.date.today()
schedule_index = 0
while schedule_index < len(schedule) and \
datetime.datetime.now() > datetime.datetime.combine(today, schedule[schedule_index][0]):
schedule_index += 1
GPIO.output(3, schedule[schedule_index][1])
# calculate next switching time
schedule_index += 1
if schedule_index == len(schedule):
schedule_index = 0
today = today + datetime.timedelta(days=1)
return datetime.datetime.combine(today, schedule[schedule_index][0])
while True:
next_time = switchLight()
time.sleep((next_time - datetime.datetime.now()).seconds + 1)

Categories