[英]Limit Rate of Print statements in Loop
我正在尋找一種有效的方法來限制 while 循環中打印語句的執行速率。 我有一個 while 循環,其中包含許多日志記錄語句,這些語句的執行取決於系統當時正在做什么(記錄錯誤消息等)。 我試圖限制每個日志語句的執行,以便如果檢測到錯誤,它不會在每次循環時記錄警告。 我不想只記錄一次錯誤,系統必須以設定的時間間隔記錄錯誤,直到不再檢測到錯誤。
我目前擁有的一個例子是:
while True:
if True: #Detect Error 1
print("Print Every Second") #Log error 1
if True: #Detect Error 2
print("Print Every 10 Seconds") #Log error 2
如果錯誤檢查驗證為 True,則每次循環運行時都會記錄錯誤。 我希望能夠限制 Logging 語句的執行速率。
我能夠使用以下代碼創建概念證明:
import time
def RateLimited(interval):
def wrapper(func):
wrapper.lastTimeCalled = [0.0]
def rateLimitedFunction(*args,**kargs):
rateLimitedFunction.elapsed = time.time() - wrapper.lastTimeCalled[0]
rateLimitedFunction.leftToWait = wrapper.minInterval - rateLimitedFunction.elapsed
if rateLimitedFunction.leftToWait>0:
pass
else:
wrapper.lastTimeCalled[0] = time.time()
return func(*args,**kargs)
return rateLimitedFunction
wrapper.minInterval = interval
return wrapper
@RateLimited(1) #Function can be run 60 times per minute (Every Second)
def Print1():
print("Print Every Second")
@RateLimited(10) #Function can be run 6 times per minute (Every 10 Seconds)
def Print2():
print("Print Every 10 Seconds")
if __name__ == "__main__":
while True:
Print1()
Print2()
這需要一個新的 function 用於必須在循環之外定義的每個打印語句。 如果可能的話,我寧願在一行中使用類似於以下語法的東西:
rateLimit("Print Every Second", 1, id=1)
rateLimit("Print Every 10 Seconds", 10, id=2)
也許看看threading 模塊。 您可以設置打印隊列並繼續處理其他內容。
一個粗略的例子:
import threading
import time
from collections import deque
class Printq:
def __init__(self, initial=[], t=2):
self.q=deque(initial)
self.t=t
threading.Timer(self.t, self.pq).start()
def pq(self):
if self.q:
print(self.q.popleft())
if self.q:
threading.Timer(self.t, self.pq).start()
def add(self, item):
self.q.append(item)
q=Printq(list('123'))
while q.q:
print("processing")
time.sleep(1)
印刷:
processing
processing
1
processing
processing
2
processing
processing
processing
3
您可以同時擁有多個不同時間的 Printq:
q1=Printq(list('1234'))
q2=Printq([e*100 for e in range(1,6)],1)
while q1.q or q2.q:
print("processing")
time.sleep(1)
印刷:
processing
processing
100
1
processing
200
processing
300
2
processing
400
processing
500
3
processing
processing
4
這是基於我的評論的一種方法。 它設置了一個Logger
class ,它將每 N 秒打印一次set
的內容(為了唯一性)。 log
方法附加到消息堆棧:
from threading import Timer
import time
class Logger():
def __init__(self, timeout=3):
self.timeout = timeout
self.msgs = set()
self._timer = None
self.start()
def start(self):
self._timer = Timer(self.timeout, self.run)
self._timer.start()
def run(self):
self.start()
print(self.msgs)
self.msgs = set()
# Restart timer
def log(self, msg):
self.msgs.add(msg)
def stop(self):
self._timer.cancel()
# start the log timer function
logger = Logger()
# Log something every second
for i in range(12):
# Log a recurring message
logger.log("msg")
# Log a unique message
logger.log(i)
time.sleep(1)
logger.stop()
output
{'msg', 0, 1, 2}
{'msg', 3, 4, 5}
{'msg', 6, 7, 8}
{'msg', 9, 10, 11}
為了滿足您最初的需求,我會嘗試構建一個標記記錄器:
我會用一個配置字典來實現它,將每個標簽名稱映射到以秒為單位的延遲,以及每個標簽的當前字典記錄下一條允許消息的時間是多少。
代碼可以是:
import time
class LimitedLogger:
def __init__(self, /, **kwargs):
for delta in kwargs.values():
if delta < 0:
raise ValueError("Tag values must be positive")
self.conf = dict(kwargs.items())
self.curr = dict()
def log(self, tag, msg):
if tag not in self.conf:
raise ValueError(f'Tag {tag} is unknown')
t = time.time()
if tag not in self.curr:
self._do_log(tag, msg, t)
else:
min_t = self.curr[tag]
if t >= min_t:
# actually print or log
self._do_log(tag, msg, t)
def _do_log(self, tag, msg, t):
print(msg)
self.curr[tag] = t + self.conf[tag]
# optionaly removed passed timeouts from curr
def clean(self):
t = time.time()
self.curr = {k: v for k, v in self.curr if v > t}
# optionaly allow calls like log.err(msg)
def __getattr__(self, name):
if name not in self.conf:
raise AttributeError(f'{LimitedLogger} has no attribute {name}')
return lambda msg: self.log(name, msg)
使用示例:
lg = LimitedLogger(warn=10, err=5)
while True:
lg.err('Err')
lg.warn('Warn')
Err <-- immediate
Warn
Err <-- after 5 seconds
Err <-- after 10 seconds
Warn
Err <-- after 15 seconds
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.