8

geventでクラシックタイマーを作成するにはどうすればよいですか?

現在gevent.spawn_laterを使用していますが、cronと同じように、「間隔でコールバックを実行する」と言うようにcore.timerを使用する方法はありますか?

def callback():
    # do something
    print '!'

timer = core.timer(10, callback)
timer.start()

outpout:
0s
10s  !
20s  !
30s  !
4

3 に答える 3

17

それはあなたがあなたの仕事をどれだけ正確にスケジュールしたいかによります。いくつかのメカニズムがあります:

このブログgevent.spawn_laterには、タイマーを作成するために使用するための巧妙なトリックがあります。

def schedule(delay, func, *args, **kw_args):
    gevent.spawn_later(0, func, *args, **kw_args)
    gevent.spawn_later(delay, schedule, delay, func, *args, **kw_args)

またはもちろん、おそらくもっと読みやすいループで単に眠ることができます:

def run_regularly(self, function, interval, *args, **kwargs):
    while True:
        gevent.sleep(interval)
        function(*args, **kwargs)

ただし、特に関数が間隔に対して完了するのに時間がかかる場合は、これらの両方が時間の経過とともにドリフトします。関数の実行にかかる時間でスリープ間隔を調整することで、補正できます。

def run_regularly(self, function, interval, *args, **kwargs):
    while True:
        before = time.time()
        function(*args, **kwargs)

        duration = time.time() - before
        if duration < interval:
            gevent.sleep(interval-duration)
        else:
            warning("function %s duration exceeded %f interval (took %f)" % (
                function.__name__, interval, duration))

これはまだドリフトしますが、それほど多くはありません...

于 2014-10-24T13:36:20.580 に答える
8

頭のてっぺんに、gevent.sleepをループで使用できます。

import gevent
import gevent.monkey

gevent.monkey.patch_all()

INTERVAL = 10

def callback():
    # do something
    print "!"

def loop():
    while True:
        gevent.sleep(INTERVAL)
        callback()

gevent.Greenlet.spawn(loop)

もちろん、このコードをcore.timerなどの優れたAPIに配置することもできます。しかし、私はあなたのためにすべての楽しみをさせます:)

于 2012-12-13T22:05:25.567 に答える
1

これは、1秒全体に初期化され、その後ドリ​​フトを修正するバージョンです。また、さまざまな目的のために、期間をいくつかのセクションに分割するために使用することもできます。

import time
import gevent

def print_time(sleep_time, tag):
    print time.time(), tag
    time.sleep(sleep_time)


def run_regularly(function, intervals, sleep_time=0.1, round_length=1):
    _, init  = divmod(time.time(), 1)
    gevent.sleep(1 - init)
    while True:
        before = time.time()
        _, offset = divmod(before, round_length)
        for div in intervals:
            function(sleep_time, div)
            after = time.time() - before
            if after < (div * round_length):
                gevent.sleep((div * round_length) - after - (offset / len(intervals)))

gevent.spawn(run_regularly, print_time, [0.2, 0.8, 1.0])

while 1:
    gevent.sleep(0.1)
于 2015-09-23T12:51:03.327 に答える