我希望这不是Python生成器的能力之外的东西,但是我想构建一个,这样每次调用该函数时,它都会在下一分钟返回到结束时间。
因此该函数读取开始和结束时间,并以分钟为单位返回时间,直到覆盖其间的所有时间。
如何实施? TIA
答案 0 :(得分:5)
datetime module非常棒。您需要了解两种数据类型:datetime
和timedelta
。 datetime
是一个时间点,而timedelta
是一段时间。基本上,我在这里要做的是一次开始并一次结束(作为datetime
对象),并逐步加1分钟。
这显然需要注意,你必须弄清楚如何将你的开始和结束时间变成datetime
。有多种方法可以执行此操作:通过the constructor,right now,UTC timestamp等等。
import datetime
def minute_range(start, end, step=1):
cur = start
while cur < end:
yield cur
cur += datetime.timedelta(minutes=step)
答案 1 :(得分:1)
因为更少的代码行总是更好(tm):
def minutes(s, e):
secs = (e - s).seconds
return (s + datetime.timedelta(minutes = x) for x in xrange(secs / 60 + 1))
像这样使用:
>>> 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
答案 2 :(得分:0)
这是我用于此目的的发电机。它可以被增强以在一段时间后停止,或者你可以将这个逻辑保留在你的调用代码中,或者在其他一些迭代器中。
import time
def sleep_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 = 0
while True:
now = time.time()
sleep_time = max(next_time - now, 0)
next_time = now + sleep_time + period
time.sleep(sleep_time)
yield next_time
您可以使用以下代码来测试行为
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),
)
def main(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.0
for 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)
从命令行调用它:
$ python cycle.py
call with -h for help.
period : 1.000000
min_duration: 0.100000
max_duration: 2.000000
cycle| 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.
将您的问题与我的答案进行比较: