Python中@monitors类装饰器的实现方案咨询
Python中@monitors类装饰器的实现方案咨询
我来帮你实现这个@monitors装饰器,刚好能满足你要的监控逻辑——让监控函数在后台线程持续运行,直到被监控的函数执行完毕,而且完全不会阻塞主函数的执行。
实现思路
核心思路是利用线程+线程安全的事件标志来控制监控线程的生命周期:
- 装饰器接收你定义的
monitor函数作为参数 - 当被装饰的函数启动时,开启一个后台线程,循环执行
monitor函数 - 用
threading.Event来标记被监控函数是否执行完成,一旦完成,监控线程就停止循环 - 被监控函数正常执行,不会被监控线程阻塞
完整实现代码
import threading import time def monitors(monitor_func): def decorator(func): def wrapper(*args, **kwargs): # 创建一个事件,用来通知监控线程停止 stop_event = threading.Event() def monitor_loop(): # 循环执行监控函数,直到收到停止信号 while not stop_event.is_set(): monitor_func() # 启动监控线程,设置为守护线程,避免程序等待它结束 monitor_thread = threading.Thread(target=monitor_loop, daemon=True) monitor_thread.start() try: # 执行被监控的主函数 result = func(*args, **kwargs) finally: # 不管主函数正常结束还是抛出异常,都通知监控线程停止 stop_event.set() # 等待监控线程完成当前的监控循环 monitor_thread.join() return result return wrapper return decorator # 你的监控函数 def monitor(): """ 这个函数会在另一个线程中运行,直到`some_cool_function`执行完毕 在示例中会执行5次(因为主函数sleep10秒,这里每次sleep2秒) 完全不会阻塞主函数 """ print(" hi from monitor!") time.sleep(2) # 被监控的函数 @monitors(monitor) def some_cool_function(): """ @monitors装饰器会让监控函数在后台线程运行 这个函数是阻塞的(正常执行自己的逻辑) """ print("this should be instantaneous!") time.sleep(10) print("done!") if __name__ == '__main__': some_cool_function()
代码关键点解释
- 带参数的装饰器:
monitors是一个装饰器工厂,先接收monitor_func,再返回真正的装饰器,这样你就能把自定义的监控函数传进去。 - 线程安全的停止标志:
threading.Event是线程安全的,主函数执行完毕后调用stop_event.set(),监控线程的循环就会终止。 - 守护线程:把监控线程设置为
daemon=True,这样即使主程序意外结束,监控线程也会自动退出,配合finally块的主动停止逻辑,双重保障避免线程泄漏。 - 异常兼容:用
try-finally确保不管被监控函数是正常结束还是抛出异常,监控线程都会被正确停止。
运行效果
执行代码后,你会看到和你期望一致的输出:
this should be instantaneous! hi from monitor! hi from monitor! hi from monitor! hi from monitor! hi from monitor! done!
主函数立刻打印第一行,然后监控函数每隔2秒打印一次,一共5次,最后主函数打印"done!",完全符合你的需求。
备注:内容来源于stack exchange,提问作者kehrazy
相关产品推荐
相关产品推荐

