Python Generator To Return Series Of Times
Solution 1:
The datetime module is quite awesome. There are two datatypes you need to know about: datetime
and timedelta
. datetime
is a point in time, while timedelta
is a period of time. Basically, what I'm going to do here is start at a time and end at a time (as a datetime
object), and progressively add 1 minute.
This obviously has the caveat that you have to figure out how to get your start and end time into a datetime
. There are a number of ways to do this: through the constructor, right now, from UTC timestamp, etc.
import datetime
def minute_range(start, end, step=1):
cur = start
while cur < end:
yield cur
cur += datetime.timedelta(minutes=step)
Solution 2:
Just because fewer lines of code is always better (tm):
def minutes(s, e):
secs = (e - s).seconds
return(s + datetime.timedelta(minutes = x)for x in xrange(secs / 60 + 1))
Use it like this:
>>>today = datetime.datetime(2012, 1, 31, 15, 20)>>>for m in minutes(today, today + datetime.timedelta(minutes = 5)):...print m
2012-01-31 15:20:00
2012-01-31 15:21:00
2012-01-31 15:22:00
2012-01-31 15:23:00
2012-01-31 15:24:00
2012-01-31 15:25:00
Solution 3:
Here is generator I use for this purpose. It could be enhanced to stop after some time, or you could keep that logic in your calling code, or in some other iterators arround.
import time
defsleep_gen(period):
"""Generator, returning not sooner, then period seconds since last call.
returned value: time of next planned start (no need to use this value)
"""
next_time = 0whileTrue:
now = time.time()
sleep_time = max(next_time - now, 0)
next_time = now + sleep_time + period
time.sleep(sleep_time)
yield next_time
You could use following code to test the behaviour
import plac
import time
from itertools import count, izip
import random
#sleep_gen to be defined here@plac.annotations(
period= ("planned period for cycling in seconds (default: %(default)s)", "positional", None, float),
min_duration=("minimal real 'action' duration in seconds (default:%(default)s)", "positional", None, float),
max_duration=("maximal 'real action' duration in seconds (default:%(default)s)", "positional", None, float),
) defmain(period = 1.0, min_duration = 0.1, max_duration = 2.0):
"""Tries to start some randomly long action in regular periods"""print"""call with -h for help.
period : %(period)f
min_duration: %(min_duration)f
max_duration: %(max_duration)f""" % locals()
try:
last_time = now = time.time()
header = ( "%5s|" +"%14s|" +"%14s|" +"%8s|" +"%8s|" +"%14s|") % ("cycle", "last_time", "now", "action", "real", "next_time")
row = "%(i) 5d|%(last_time)14.2f|%(now)14.2f|%(action_dur)8.3f|%(real_dur)8.3f|%(next_time)14.2f|"print header
action_dur = real_dur = 0.0for i, next_time in izip(count(), sleep_gen(period)):
#we care about starting the action on time, not ending
now = time.time() #sleep_gen just tried to keep the period on schedule
real_dur = now - last_time
print row % locals()
last_time = now
#performing the "action"
action_dur = random.random() * (max_duration - min_duration) + min_duration
time.sleep(action_dur)
except KeyboardInterrupt:
print"...cancelled."if __name__ == "__main__":
plac.call(main)
Calling it from command line:
$ python cycle.py
callwith-h for help.
period : 1.000000
min_duration: 0.100000
max_duration: 2.000000cycle| last_time| now| action|real| next_time|0|1337368558.55|1337368558.55|0.000|0.002|1337368559.55|1|1337368558.55|1337368559.59|1.042|1.042|1337368560.59|2|1337368559.59|1337368561.32|1.722|1.723|1337368562.32|3|1337368561.32|1337368562.32|0.686|1.000|1337368563.32|4|1337368562.32|1337368563.32|0.592|1.000|1337368564.32|5|1337368563.32|1337368564.75|1.439|1.439|1337368565.75|6|1337368564.75|1337368566.08|1.323|1.323|1337368567.08|7|1337368566.08|1337368567.08|0.494|0.999|1337368568.08|8|1337368567.08|1337368568.20|1.120|1.121|1337368569.20|9|1337368568.20|1337368569.20|0.572|1.000|1337368570.20|10|1337368569.20|1337368570.20|0.586|1.000|1337368571.20|11|1337368570.20|1337368571.20|0.309|0.999|1337368572.20|12|1337368571.20|1337368572.20|0.290|1.000|1337368573.20|13|1337368572.20|1337368573.25|1.052|1.053|1337368574.25|14|1337368573.25|1337368574.25|0.737|1.000|1337368575.25|15|1337368574.25|1337368575.83|1.579|1.579|1337368576.83|
...cancelled.
Comparing your question with my answer:
- generator: yes, it is
- enter start time: I use just the current moment (what could be what one often needs)
- enter end time: Stop calling the generator at that moment. Or modify generator to loop only some number of loops or end at certain time.
Post a Comment for "Python Generator To Return Series Of Times"