How to write sleep function for my controlled DateTime? - python

I created a variable
current_time = datetime.datetime.now()
I am increasing time a second in an iteration of while loop.
while True:
current_time = current_time + datetime.timedelta(seconds=1)
current_time is a global variable. I am using it as time in my modules. I want to sleep some functions based on this time.
but if I use
time.sleep()
this will use system time.
So How can I create a sleep function that depends on my current_time?
Edit:- I am implementing an algorithm, storing a value lets call it scheduling time. I want to wait for function up to scheduling time and on time execute the function. There are some functions that will update the scheduling time. So it is a repetitive process. I look for the scheduler library but didn't find anything to use, current_time as time.
I don't want to use system time directly, for me current_time is the time of the system/program. So current_time will increase with speed of the while loop. I am just running while loop without any relation with time, just want to update my time faster because I am using the code to generate months of data in hours. I want to keep my code as virgin as possible. I want to generate data based on this algorithm and will replace my artificial time with the real system time for production use.

If you are trying to sleep until current_time is reached, you can do:
while datetime.datetime.now() <= current_time:
time.sleep(1)
Assuming I'm understanding correctly that your current_time is greater than the actual current time from datetime.datetime.now().

Related

Terminate thread and/or scheduler

I'm more or less a Python beginner, so I might be using the wrong tools for the job. Or maybe I'm using the correct tools but not correctly.
Here's what I'm trying to do.
def stand_by(self, evt_time, number):
"""Waiting for scheduled time
Starts a scheduler in a separate thread that will run in the background
until a specific time is reached, usually a time in a flight's
schedule. Once that specific time is reached, the program will regularly
check if the state of the flight has changed as expected.
Args:
evt_time (:obj:`datetime`): The scheduled time of the status change.
Schedulers need Unix timestamps, so this has to be converted
inside the function.
number (str): Flight number of the flight that should be observed.
This function itself does not need it but it has to be passed on
as an argument.
"""
# evt_time is given in UTC time but needs to be checked against
# system time
scheduler = sched.scheduler(time.time, time.sleep)
tz = pytz.timezone(player.tz)
# Turns the event time from datetime UTC into datetime player actual
evt_time = pytz.utc.localize(evt_time).astimezone(tz)
# Turns the datetime object into a UNIX time stamp
evt_time = evt_time.timestamp()
threading.Thread(target=lambda: scheduler.enterabs(
evt_time, 2, check_dep, [number])).start()
scheduler.run()
The user selects a flight they want to "board". Let's say it's 1 PM and the flight is scheduled to leave at 2 PM. The program will start a scheduler that later starts a "listener" at 2 PM to see if the flight has departed. To enable the user to continue using the program until 2 PM, the scheduler is running in a separate thread. I'm trying to figure out how I can terminate that thread and/or scheduler if the user decides to choose a different "flight" before 2 PM. I can't seem to find an elegant way of terminating threads.
I have found threading.timer, which can be cancelled, but that takes a time interval, not a time object...
I'm not married at all to this function. What I need is a way to run another function at a fixed time so that the program remains usable and that can be terminated if the user changes their mind. Thanks a lot for ideas!

How accurate is python's time.sleep() for long time periods?

I'm wondering how accurate python's time.sleep() method is for longer time periods spanning from a few minutes up to a few days.
My concern is, that there might be a drift which will add up when using this method for longer time periods.
Alternatively I have come up with a different solution to end a loop after a certain amount of time has passed:
end = time.time() + 10000
while 1:
if time.time() > end:
break
This is accurate down to a few milliseconds which is fine for my use case and won't drift over time.
Python's time.sleep() function is accurate and should be used in this case as it is simpler and easier to run. An example is
time.sleep(10000) # will stop all running scripts in the same pid
Using a bare while statement without any threshold will use a lot of your resources, which is why you should use a time.sleep expression to reduce this. You also should have used the while statement condition statement as this will make sure your while statement closes.
As shown below
end = time.time() + 10000
while end > time.time(): # ensures to end when time.time (now) is more than end
time.sleep(0.001) # creates a 1 ms gap to decrease cpu usage
I would recommend using the pause module, you can get millisecond precision over a period of days. No need to roll your own here.
https://github.com/jgillick/python-pause
Python's time.sleep() is accurate for any length of time with two little flaws:
The time t must be considered "at least t seconds" as there may be a
number of system events that are scheduled to start at the precise moment
"time when started" + t.
The sleep may be interrupted if the signal handler raises an exception.
I think, but am not certain, that these flaws are found in most programming languages.

How to get the RTC time in python Windows OS

Currently making use of datetime.datetime.now() from python code to obtain the date/time stamp. However this is the date/timezone that is set on the system which can be changed/altered.
How can i retrieve the real time i.e RTC time from python. Any help will be greatly appreciated.
If you are using Linux/Unix, you can get the system-wide real time clock with the time module from the standard library, as follows:
import time
rtc = time.clock_gettime(time.CLOCK_REALTIME)
print("System RTC = {rtc}")
> System RTC = 1549619678.899073
For Windows, RTC is not available. There are a variety of other clocks you could use, depending on your application, which wouldn't be affected by updates to system time. For instance, if you are trying to measure time between two separate calls, and don't want this to be affected by changes to system datetime/timezone, you can use time.monotonic() which is available on Windows as well. However, is only useful relative to another call to time.monotonic() (i.e. for measuring duration) and does not have a defined reference point, so you can't do a call to time.monotonic() to ask "what time is it?"

scheduling for an exact time with monotonic time

I have a scheduling function and a scheduler with a queue of future events ordered by time. I'm using UNIX timestamps and the regular time.time(). One fragment of the scheduler is roughly equivalent to this:
# select the nearest event (eventfunc at eventime)
sleeptime = eventtime - time.time()
# if the sleep gets interrupted,
# the whole block will be restarted
interruptible_sleep(sleeptime)
eventfunc()
where the eventtime could be computed either based on a delay:
eventtime = time.time() + delay_seconds
or based on an exact date and time, e.g.:
eventtime = datetime(year,month,day,hour,min).timestamp()
Now we have the monotonic time in Python. I'm considering to modify the scheduler to use the monotonic time. Schedulers are supposed to use the monotonic time they say.
No problem with delays:
sleeptime = eventtime - time.monotonic()
where:
eventtime = time.monotonic() + delay_seconds
But with the exact time I think the best way is to leave the code as it is. Is that correct?
If yes, I would need two event queues, one based on monotonic time and one based on regular time. I don't like that idea much.
As I said in the comment, your code duplicates the functionality of the sched standard module - so you can as well use solving this problem as a convenient excuse to migrate to it.
That said,
what you're supposed to do if system time jumps forward or backward is task-specific.
time.monotonic() is designed for cases when you need to do things with set intervals between them regardless of anything
So, if your solution is expected to instead react to time jumps by running scheduled tasks sooner or later than it otherwise would, in accordance with the new system time, you have no reason to use monotonic time.
If you wish to do both, then you either need two schedulers, or tasks with timestamps of the two kinds.
In the latter case, the scheduler will need to convert one type to the other (every time it calculates how much to wait/whether to run the next task) - for which time provides no means.

How to import rain data for purposes of upload to Wunderground

I have a program that counts pulses (Hall effect sensor) on a rain gauge to measure precipitation. It runs continuously and counts a number of pulses every 5 minutes that then translates into a rain amount. After an hour (12 - 5min. measurements, I add the total and this is the hourly rainfall. I have structure this program so that it drops the oldest measurement and adds the new one each 5 minutes after an hour, and so I have a running hourly rain output, termed "totalrainlasthour".
My problem is that I want to upload this data to weather underground using a separate program that includes other data such as wind speed, temp, etc. This upload takes place every 5 minutes. I want to include the current value of "totalrainlasthour", and use it in the upload.
I tried a "from import" command but the more I read, that doesn't look like it would work.
from rainmodule import totalrainlasthour
print totalrainlasthour
Is there a way can I pull in the current value of a variable from a separate program?
As far as I know, there's no good way for a python script that just starts up to access the values from inside an already-running Python instance. However, there are a few workarounds that you can try.
If it's acceptable for your weather uploading script to be running constantly, you could structure it to look something like this:
import time
import rainmodule
import windmodule
# etc
def start():
# instantiate classes so you can keep track of state
rain = rainmodule.RainCollection()
wind = windmodule.WindCollection()
# etc
prev_time = time.time()
while True:
rain.loop()
wind.loop()
# etc
now = time.time()
if now - prev_time > (60*60*5):
prev_time = now
totalrainlasthour = rain.totalrainlasthour
winddata = wind.data
# upload code here
if __name__ == '__main__':
start()
This method assumes that every one of your data collection modules can be modified to run iteratively within a "master" while loop.
If you can't wrangle your code to fit this format, (or the loop methods for some modules take a long time to execute) then you could perhaps launch each of your modules as a process using the multiprocessing or threading modules, and communicate using some synchronized data structure or a queue.
An alternative solution might be to create a database of some sort (Python comes bundled with sqlite, which could work), and have each of the scripts write to that database. That way, any arbitrary script could run and grab what it needs to from the database without having to tie in to the other data collection modules.
The only potential issue with using sqlite is that since it's lightweight, it supports only one writer at a time, so if you're making a huge amount of changes and additions to the database, it may end up being a bottleneck.

Categories

Resources