I'm busy with an python script on a raspberry pi for a rain gauge.
The script need to count the tips of the bucket and write the total rain amount every 5 minutes to a csv file. The script does the writing now every 299.9 seconds but I want it to write every exact 5 minutes, for example: 14:00, 14:05, 14:10 and so on.
Is there anyone who could help me out?
Thanks in advance!
Use a cronjob, for raspberry pi go with crontab
https://www.raspberrypi.org/documentation/linux/usage/cron.md
You will find lots of helpful functions in the datetime module:
from datetime import datetime, timedelta
# Bootstrap by getting the most recent time that had minutes as a multiple of 5
time_now = datetime.utcnow() # Or .now() for local time
prev_minute = time_now.minute - (time_now.minute % 5)
time_rounded = time_now.replace(minute=prev_minute, second=0, microsecond=0)
while True:
# Wait until next 5 minute time
time_rounded += timedelta(minutes=5)
time_to_wait = (time_rounded - datetime.utcnow()).total_seconds()
time.sleep(time_to_wait)
# Now do whatever you want
do_my_thing()
Note that when do_my_thing() is called it will actually be fractionally after the exact time in time_to_round, because obviously computers can't do work in precisely zero time. It's guaranteed not to wake up before that time though. If you want to refer to the "current time" in do_my_thing(), pass in the time_rounded variable so that you get neat timestamps in your log file.
In the code above I've deliberately recomputed time_to_wait each time, rather than just setting it to 5 minutes after the first time. That's so that the slight delay I just mentioned don't gradually snowball after you've been running the script for a long time.
Related
I'm trying to use the schedule module to do some basic scheduling in a continuously updating script.
Is there a way to set a schedule to run every "x" hours, 'on the hour'?
For example, I'd like to have a function that runs at: [1:02pm, 2:02pm, 3:02pm, 4:02pm] regardless of when I run the script in the first place. In other words, simply doing "schedule.every(1).hours.' doesn't work because I can't guarantee what time the script is run in the first place.
Thanks!
Here you can find examples for case you trying to achieve.
schedule.every().hour.at(":02").do(job)
Here is a simple script:
from datetime import datetime
import time
# scheduled hours in 24-hour format
hours = ["13:2", "14:2", "15:2", "16:2"]
# your function
def foo():
pass
while True:
now = datetime.now() # gets current datetime
hour = str(now.hour) # gets current hour
minute = str(now.minute) # gets current minute
current_time = f"{hour}:{minute}" # combines current hour and minute
# checks if current time is in the hours list
if current_time in hours:
foo()
time.sleep(60) # waits a minute until it repeats
Please note that it will check every minute at the same time when you ran it, and not when the new minute starts. (For instance, if you run it in the middle of the minute, it will check again in the middle of the next minute)
I want that a specific time of the day (for example 10:00:00), one of my if condition activates.
For example:
if time is 10:00:00:
print("Hello world")
Imortant: I already read this: Python script to do something at the same time every day
But I don't want to use a function!
If you do not one to use a function but need to run a simple script at certain times, you may use crons/job schedulers for this.
Windows and Linux both supports cron operations.
If you want to do this programmatically instead of relying on operating system tools you need to write a service or a long running process for it.
You could easy use datetime to help you with that.
import datetime
from time import sleep
timing = [10, 0, 0] # Hour, minute, second, in 24 hour time
while True: # Repeat forever
now = datetime.datetime.now()
data = [now.hour, now.minute, now.second]
if data == timing:
# Code to be executed
print("Hello World")
#######
sleep(1) # To ensure the command is not repeated again
# break # Uncomment this if you want to execute the command only once
Make sure that I indented it properly, because one space can tick python off :).
The way that it works:
import datetime and from time import sleep import the necessary modules and functions that you will need.
Modules needed:
datetime
time.sleep
Now we're set.
timing = [10,0,0] sets the time that you want to use (you'll see why later)
while True repeats the loop... on and on and on.
now = datetime.datetime.now() creates a shortcut for such a long piece of text.
data == timing makes sure the time matches the timing you asked.
Note that the timing is in UTC
Go to Getting the correct timezone offset in Python using local timezone to know how to find your offset.
An offset of UTC-0200 (Or -7200 seconds) means that you need to ADD 2 hours to your time to get UTC. Or, if your time zone is UTC+0200, SUBSTRACT 2 hours from your time.
I'm trying to use the Schedule module to run a task during specific days of the week and specific hours, basically business hours. The while loop will work when the condition is true but once it's false it will not run again to see if the time frame still applies. I would have to restart the script for it to work.
I'm pretty new to Python and self taught. This is my first time posting here so please correct me if I've formatted this badly or haven't included enough information. I've tried scouring the forums to get around this particular issue I'm having but haven't found an answer; I'm probably searching wrong. It may be a simple issue but I've been wracking my brain for a few days. This is a small test portion of code that I'm trying to use for another script. Other people have recommended Cron but since this is going into a larger script, I only need a section of it to run on a task and not the whole thing.
from datetime import datetime as dt
import schedule
import time
def weekdayJob(x, i=None):
week = dt.today().weekday()
if i is not None and week < 5 and dt.now().hour in range(9,17):
schedule.every(i).minutes.do(x)
def printJob():
timestamp = time.strftime("%Y%m%d-%H%M")
print(f"test {timestamp}\n")
weekdayJob(printJob, 5)
while True:
schedule.run_pending()
time.sleep(5)
I've also tried
from datetime import datetime as dt
import schedule
import time
def weekdayJob(x, i=None):
week = dt.today().weekday()
if i is not None and week < 5 and dt.now().hour in range(9,17):
schedule.every(i).minutes.do(x)
def printJob():
timestamp = time.strftime("%Y%m%d-%H%M")
print(f"test {timestamp}\n")
x = 1
while x == 1:
weekdayJob(printJob, 1)
time.sleep(5)
while True:
schedule.run_pending()
time.sleep(5)
I figured that putting the scheduled job in the while loop would make it constantly check to see if the conditional statement was true but that doesn't seem the case. How would I make it so this script is constantly checking if weekdayJob is within the desired time frame so I don't have to restart the script.
Move the conditional statement into the printjob function, and do not use nested while loop (code here switches between business hours and non business hours). schedule tasks run continuously, but your function if-statement only runs during your defined business hours. Here running at 1minute interval (testing odd vs even minutes), you can spec your own business hours:
import datetime as dt
import schedule, time
from datetime import datetime
def printJob():
week = dt.datetime.today().weekday()
timestamp = time.strftime("%Y%m%d-%H%M")
if week < 5 and datetime.now().minute % 2 ==0: # in range(9,17):
print(f"business hours test...EVEN minutes... {timestamp}\n")
# your business hours function here...
else:
print(f'go home...test... ODD minutes... {timestamp}\n')
schedule.every(1).minute.do(printJob)
while True:
schedule.run_pending()
I want to pause my code every hour mark, i.e 11:00pm, 12:00am, 1:00am, etc.
How do I go about doing this?
You have two ways to do this:
cron method
Add a cron job for your script that gets executed every hour:
#hourly python /path/to/script
code method
Create an infinite loop within your code that runs every hour (have it sleep for 60 minutes). Or, create an infinite loop within your code that sleeps every minute, have it periodically check what time it is, and if it's on the hour with different delta hour than the current hour, have it run the job.
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(60) # 60 seconds
# add some way to exit the infinite loop
The scenario is as follows: given a totally arbitrary starting date in UTC there is an event that repeats every 24 hours. I need to calculate, given the current local time, how much time is left before the next event.
Ideally an ideal function would do:
time_since_start = now - start_time
remaining_seconds = time_remaining(time_since_start)
EDIT: Some clarifications. start_time defines the "epoch", the global start time since the event started repeating. Secondly, now is an arbitrary time occurring after start_time, local.
The issue is not calculating the occurrence of the next event (which would be simply adding 24 hours to start_time) but if I pick a time that falls between one event and the other, how much time is left before the next event.
I'd opt seconds as they can be quickly parsed into days, minutes and hours. Usage of datetime would be preferred (but not required) over other third-party modules as I am trying to reduce the number of dependencies.
I tried using datetime and timedelta, but the difference is always incorrect. What is the best way to proceed there?
What you want is start_time - now + (one day)