Scheduling a task on python - python

I want to run a program that runs a function every 4 hours.
What is the least consuming way to do so?

Simlest way I can think of (in python since the post is tagged with python):
import time
while True:
do_task()
time.sleep(4 * 60 * 60) # 4 hours * 60 minutes * 60 seconds

You can use sched module
Here are the docs
https://docs.python.org/3.4/library/sched.html

Use the build in timer thread:
from threading import Timer
def function_to_be_scheduled():
"""Your CODE HERE"""
interval = 4 * 60 * 60 #interval (4hours)
Timer(interval, function_to_be_scheduled).start()

Related

Sleep until a certain amount of time has passed

I'm writing a function in Python that waits for an external motor to finish moving, but the amount of time it takes for the motor to move can be variable. I want to standardize the time in between each move — for example, they should all take 30 seconds.
Is there a way to implement a sleep function so that it sleeps the required amount of time until 30 seconds has passed?
For example:
if the motor takes 23 seconds, the function will wait until 30 seconds have passed, so it will sleep 7 seconds.
It sounds like don't want to sleep for 30 second but rather pad the time it takes to perform an activity with a sleep so that it always takes 30 seconds.
import time
from datetime import datetime, timedelta
wait_until_time = datetime.utcnow() + timedelta(seconds=30)
move_motor()
seconds_to_sleep = (wait_until_time - datetime.utcnow()).total_seconds()
time.sleep(seconds_to_sleep)
if you are going to be doing this in multiple places you can create a decorator that you can apply to any function
import functools
import time
from datetime import datetime, timedelta
def minimum_execution_time(seconds=30)
def middle(func)
#functools.wraps(func)
def wrapper(*args, **kwargs):
wait_until_time = datetime.utcnow() + timedelta(seconds=seconds)
result = func(*args, **kwargs)
seconds_to_sleep = (wait_until_time - datetime.utcnow()).total_seconds()
time.sleep(seconds_to_sleep)
return result
return wrapper
You can then use this like so
#minimum_execution_time(seconds=30)
def move_motor(...)
# Do your stuff
It depends on how you are monitoring the runtime of your motor.
For the sake of example, let's assume you have that value stored in a variable,
slowdown_time
#slowdown_time is the variable that stores the time it took for the motor to slow down.
import time
desired_interval = 30 #seconds
sleep_time = desired_interval - slowdown_time
#sleep for remaining time
time.sleep(sleep_time)
Hope this is helpful!

How to add a component of randomness to a schedule

I am trying to schedule a job to run every 3 minutes on average, with a component of randomness between +/- 30 seconds. So the next job runs anywhere between 2mins 30secs - 3mins 30secs later.
This code works nicely for exactly 3 minutes, but I can't think of a way to introduce the 30 secs of randomness:
import schedule
def job:
print('hi')
schedule.every(3).minutes.do(job)
You need to look up the random module that comes with python.
import schedule
import random
def job():
print('hi')
two_mins_30 = 2 * 60 + 30
schedule.every(two_mins_30 + random.randint(0, 60)).seconds.do(job)
This calculation is: two minutes, 30 plus up to another minute at random.
Update:
It turns out you can directly do this with schedule because the Job class has a to() method:
schedule.every(two_mins_30).to(two_mins_30 + 60).seconds.do(job)

How to sleep python script for xx minutes after every hour execution?

I am trying to make a python script that works in a loop mode with iteration through a text file to run for periods of one hour and make 30minute pauses between each hour loop .
After some searching I found this piece of code :
import datetime
import time
delta_hour = 0
while:
now_hour = datetime.datetime.now().hour
if delta_hour != now_hour:
# run your code
delta_hour = now_hour
time.sleep(1800) # 1800 seconds sleep
# add some way to exit the infinite loop
This code has a few issues though :
It does not consider one hour periods since the script starts running
It does not seem to work continuously for periods over one hour
Considering what I am trying to achieve (running script 1hour before each time it pauses for 30mins) what is the best approach to this ? Cron is not an option here .
For clarification :
1hour run -- 30min pause -- repeat
Thanks
Here is a so simple code, I have written for teaching purposes, which is very clear
from datetime import datetime
class control_process():
def __init__(self, woking_period, sleeping_period):
self.woking_period = woking_period # working period in minutes
self.sleeping_period = sleeping_period # sleeping period in minutes
self.reset()
def reset(self):
self.start_time = datetime.utcnow() # set starting point
def manage(self):
m = (datetime.utcnow() - self.start_time).seconds / 60 # how long since starting point
if m >= self.woking_period: # if exceeded the working period
time.sleep(self.sleeping_period * 60) # time to sleep in seconds
self.reset() # then reset time again
return # go to continue working
cp = control_process(60, 30) # release for 60 minutes and sleep for 30 minutes
while True: # you code loop
cp.manage()
'''
your code
'''
in which 'control_processobject - I calledcp- callscp.manage()` inside your executing loop.
you reset time via cp.reset() before going in the loop or whenever you want
Based on Comments
The simplicity I mean is to add this class to your general library so you can use it whenever you want by instantiation of cp then one or two controlling functions 'cp.manage()` which control the working cycles, and cp.reset() if you want to use it in another location of the code. I believe that use a function is better than a long condition statement.
Using the default library you could do something like call the script itself using subprocess. By checking whether conditions are met the process could do a task and call itself. Extending the logic with a kill pill would make it stop (I leave that up to you).
import argparse, time
from subprocess import call
DELAY = 60 * 30 # minutes
WORK_TIME = 60 * 60 # minutes
parser = argparse.ArgumentParser()
parser.add_argument("-s",
help = "interval start time",
type = float,
default = time.time())
parser.add_argument("-t",
help = "interval stop time",
type = float,
default = time.time() + WORK_TIME)
def do_task():
# implement task
print("working..")
return
if __name__ == "__main__":
args = parser.parse_args()
start = args.s
stop = args.t
# work
if start < time.time() < stop:
do_task()
# shift target
else:
start = time.time() + DELAY
stop = start + WORK_TIME
call(f"python test.py -t {stop} -s {start}".split())
The simplest solution I could come up with was the following piece of code, which I added inside my main thread :
start_time = int(time())
... #main thread code
#main thread code end
if int(time() - start_time >= 60 * 60):
print("pausing time")
sleep(30 * 60)
start_time = int(time())
From the moment the script starts this will pause every hour for 30mins and resume afterwards .
Simple yet effective !

How to write a while loop that will run base in hours

I'm creating a test for Google Assistant based on while loop. The code will play a long mp3 file and I'm try to identify if the assistant will do a false trigger and count how many times.
I'm running on pycharm/pytest and getting the trigger status by UIAutomator provided by Google.
import android
import time
play_music(music.mp3)
start_time = time.time()
trigger = 0
hours = 1
command_timeout = hours * 60 * 60
while trigger < 3 or time.time() - start_time < command_timeout:
if trigger_screen.is_in_screen():
trigger += 1
time.sleep(10)
stop_music()
The conditions to stop the loop is 3 false triggers or one hour of test, but the loop isn't stop after one hour of test, could someone help me?
You're using an or statement when you should be using an and statement:
while trigger < 3 and time.time() - start_time < command_timeout:
With your current code, the while loop only terminates when BOTH conditions are
False, when you really want it to terminate when either one or the other is False.
You need to swap the or in your code with and like shown below:
import android
import time
play_music(music.mp3)
start_time = time.time()
trigger = 0
hours = 1
command_timeout = hours * 60 * 60
while trigger < 3 and time.time() - start_time < command_timeout:
if trigger_screen.is_in_screen():
trigger += 1
time.sleep(10)
stop_music()
Bassically the code you wrote continues the loop as long as one of the conditions is met, which explains why your music continued to play (less than 3 triggers so the loop still runs)

How can I repeat a program every x seconds for x seconds(in my case, every 3 seconds for 30 seconds)

My programming teacher had assigned me a simple task of creating a program that randomly generates a number between 1-100 every 3 seconds for 30 seconds. Here is my program so far:
import random
import time
while True:
print(random.randint(0,100))
time.sleep(3)
At the moment, it only prints every 3 seconds infinitely. I want it to repeat it for only 30 seconds.
Thanks for your consideration!
import random
import time
a=time.clock()
while ((time.clock()-a)<30):
print(random.randint(0,100))
time.sleep(3)
It's an assignment, so we cannot solve it for you. However, we can guide you to the correct module to use, that's sched documented here https://docs.python.org/3.6/library/sched.html
Make use of time.time() function. It will give you the time in seconds since January 1, 1970, 00:00:00 (UTC).
import random
import time
counter = 30
start_time = time.time()
while time.time() - start_time < counter:
print(random.randint(0,100))
time.sleep(3)
Use a for range loop like so:
import time
import random
a=time.clock()
for x in range(10):
print(random.randint(1,100))
time.sleep(3)

Categories

Resources