2012-11-03 39 views
6

Làm thế nào tôi có thể làm cho bộ đếm thời gian cổ điển trong gevent?somethig như cron (timer) trong gevent

Tôi hiện đang sử dụng gevent.spawn_later nhưng có cách nào để sử dụng core.timer như nói "làm gọi lại trên khoảng thời gian" giống như cron không?

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

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

outpout: 
0s 
10s ! 
20s ! 
30s ! 
+1

Hmm, tại sao greenlet lặp lại vô tận, gọi điện thoại và ngủ, không đủ? –

+0

Tôi sử dụng điều này trong gunicorn vì vậy nó là máy chủ web, và tôi không biết làm thế nào để làm điều đó. Tôi chỉ có chức năng xử lý, nhưng tôi có lẽ có thể chèn mã đó trước đó. Dường như không tốt để làm điều đó bởi vì nếu tôi cần 10 giờ, tôi cần 10 cuộc gọi lại. Điều đó thậm chí có hiệu quả với gunicorn không? – bradojevic

Trả lời

7

Trên đỉnh đầu của tôi, bạn có thể sử dụng gevent.sleep trong một vòng lặp:

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) 

Tất nhiên, bạn có thể đặt mã này trong một API đẹp như core.timer. Nhưng tôi sẽ để tất cả những điều thú vị cho bạn :)

+0

thời gian trôi dạt từ cuộc gọi lại() – whi

12

Nó phụ thuộc chính xác đến mức bạn muốn công việc của mình được lên lịch. Có một vài cơ chế:

This blog có một trick gọn gàng cho việc sử dụng gevent.spawn_later để tạo ra một bộ đếm thời gian:

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) 

Hoặc tất nhiên bạn chỉ có thể ngủ trong một vòng lặp mà có lẽ dễ đọc hơn:

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

Tuy nhiên, cả hai điều này sẽ trôi qua theo thời gian, đặc biệt nếu chức năng của bạn cần thời gian để hoàn thành tương ứng với khoảng thời gian. Bạn có thể bù đắp bằng cách điều chỉnh khoảng thời gian ngủ vào thời điểm các chức năng cần thiết để thực hiện:

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)) 

này sẽ vẫn trôi, chỉ cần không phải là khá nhiều ...

1

Dưới đây là một phiên bản mà khởi cho toàn thể thứ hai và sau đó sửa chữa cho bất kỳ sự trôi dạt nào. Nó cũng có thể được sử dụng để chia một khoảng thời gian thành nhiều phần cho các mục đích khác nhau:

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)