Генератор Python для возвращения серии раз - PullRequest
1 голос
/ 31 января 2012

Я надеюсь, что это не выходит за рамки возможностей генераторов Python, но я хотел бы построить так, чтобы при каждом вызове функции она возвращалась в следующую минуту вплоть до времени окончания.

Таким образом, функция считывает время начала и окончания и возвращает время каждую минуту, пока не будет покрыто все промежуточное время.

Как это будет реализовано? ТИА

Ответы [ 3 ]

5 голосов
/ 31 января 2012

Модуль datetime довольно классный. Вам необходимо знать два типа данных: datetime и timedelta. datetime - это момент времени, а timedelta - это период времени. По сути, здесь я собираюсь начать и закончить одновременно (как объект datetime) и постепенно добавлять 1 минуту.

Это, очевидно, предостережение о том, что вы должны выяснить, как получить начальное и конечное время в datetime. Есть несколько способов сделать это: через конструктор , прямо сейчас , из метку времени UTC и т. Д.

import datetime

def minute_range(start, end, step=1):
   cur = start
   while cur < end:
      yield cur
      cur += datetime.timedelta(minutes=step)
1 голос
/ 31 января 2012

Просто потому, что меньше строк кода всегда лучше (тм):

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
0 голосов
/ 18 мая 2012

Вот генератор, который я использую для этой цели. Можно было бы улучшить остановку через некоторое время, или вы могли бы сохранить эту логику в своем вызывающем коде или в некоторых других итераторах arround.

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.

Сравнение вашего вопроса с моим ответом:

  • генератор: да, это
  • введите время начала: я использую только текущий момент (что может быть тем, что часто нужно)
  • введите время окончания: прекратите вызывать генератор в этот момент. Или измените генератор так, чтобы он зацикливался только на определенном количестве циклов или заканчивался в определенное время.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...