2015-06-18 25 views
5

Tôi đã tìm thấy this trang trí trăn giới hạn tốc độ dựa trên các lớp redis. Làm thế nào tôi có thể viết một trang trí tương tự chỉ sử dụng những gì có sẵn trong thư viện chuẩn có thể được sử dụng như sau?Trang trí trăn giới hạn tỷ lệ

def ratelimit(limit, every): 
    # python magic 

@ratelimit(limit=1, every=2) 
def printlimited(x): 
    print x 

# print one number every two seconds 
for x in range(10): 
    printlimited(x) 

answers khác trên stackoverflow nhưng họ không cho phép để xác định mẫu số.

Trả lời

7

Bạn có thể sử dụng số threading.Semaphore để đếm và chặn các yêu cầu vượt quá giới hạn, kết hợp với threading.Timer để lên lịch cho chức năng phát hành semaphore.

from threading import Semaphore, Timer 
from functools import wraps 

def ratelimit(limit, every): 
    def limitdecorator(fn): 
     semaphore = Semaphore(limit) 
     @wraps(fn) 
     def wrapper(*args, **kwargs): 
      semaphore.acquire() 
      try: 
       return fn(*args, **kwargs) 
      finally:     # don't catch but ensure semaphore release 
       timer = Timer(every, semaphore.release) 
       timer.setDaemon(True) # allows the timer to be canceled on exit 
       timer.start() 
     return wrapper 
    return limitdecorator 
+0

Điều này sẽ không phát hành semaphore nếu hàm được bao bọc đưa ra ngoại lệ. Bạn có thể sử dụng mệnh đề 'try..finally' để đảm bảo điều đó xảy ra. –

+0

@PaulMFurley bắt thú vị! Tôi đã chỉnh sửa mã, bạn có kiểm tra nó không? –

Các vấn đề liên quan