Python实现生产者消费者、装饰器模式
生产者-消费模式
Python通常使用 阻塞队列 实现 生产者-消费者模式,计算后端Trace系统 使用了这一模式,类似如下:
# -*- coding: UTF-8 -*-
import eventlet
from eventlet import queue
# pool 和 q 的大小可以动态调整
pool = eventlet.GreenPool(size=5)
q = queue.Queue(maxsize=3)
def producer(idx):
item = "数据-%s" % idx
# 每次调用 put() 时,unfinished_tasks 计数器加 1
q.put(item)
print("生产: %s" % item)
eventlet.sleep(0.1)
# 发送终止信号(有几个消费者就发几个)
q.put(None)
def consumer(idx):
while True:
item = q.get()
if item is None: # 收到终止信号
# 每次调用 task_done() 时,unfinished_tasks 计数器减 1
# q.task_done()
print("消费者-%s 退出" % idx)
break
print("消费: %s (由消费者-%s处理)" % (item, idx))
# q.task_done()
eventlet.sleep(0.3)
# 启动生产者和消费者
for i in range(3):
pool.spawn_n(producer, i)
for i in range(3):
pool.spawn_n(consumer, i)
# join() 会阻塞直到 unfinished_tasks 变为 0
# q.join()
# print("所有任务完成")
# 等待所有协程完成(可选,join() 后通常已无活跃协程)
pool.waitall()
print("所有任务完成")
装饰器模式
计算后端Trace系统 使用了装饰模式实现 trace信息采集器,类似如下:
import functools
import sys
from abc import ABC
# trace信息采集装饰器
def trace(service):
def decorator(func):
# functools.wraps(func) 会将原函数(func)的 __name__、__doc__、__module__ 等属性复制到包装函数(wrapper)上。
@functools.wraps(func)
def wrapper(*args, **kwargs):
# 前置逻辑:模拟构建追踪上下文
print("build trace info for %s" % service.name)
try:
# 执行原函数
return func(*args, **kwargs)
except Exception as e:
# 异常处理
print("catch err: %s" % str(e))
raise e
finally:
# 后置逻辑:模拟上传日志
print("upload to skywalking")
return wrapper
return decorator
# 使用装饰器
@trace(service=sc.Component.NovaApi)
def rebuild_vm_in_nova_api():
print("begin to rebuild instance")
raise Exception("test err")
# 调用
rebuild_vm_in_nova_api()

浙公网安备 33010602011771号