Python WorkerThread设计实现

来源:互联网 发布:淘宝拆车喇叭 编辑:程序博客网 时间:2024/06/15 13:51

WorkerThread 设计

具体细节

threading.local

local的用法:

  • 可以通过设置简单threading.local,并设置相应的LocalManager来管理local
  • 还可以继承自local class, 这种方法可以很有效的实现local的默认值, 方法, 初始化. 注意如果定义了 __init__ 函数, 将会在每个特定的线程中进行 __init__函数的调用,这对于初始化每一个线程的字典来说非常的重要
  • threading.local() :类表示线程本地变量. 线程本地变量对于特定的线程不同. 管理线程本地变量threading.local, 如 mydata = threading.local() mydata.x = 1

继承自threading.local的用法如下(具体见官方源码):

class MyLocal(local):    number = 2    initialized = False    def __init__(self, **kw):        if self.initialized:            raise SystemError('__init__ called two many times')        self.initialized = True        self.__dict__.update(kw)    def squared(self):        return self.number**2

subclasses 可以定义 __slots__, 但是并不是线程本地变量, 而是通过线程共享

LocalManager

LocalManager :该类用来管理本地线程变量,中的具体字段.

class LocalManager(object):    def __init__(self, local_obj):        self.local_obj = local_obj    def to_dict(self):        rv = {}        for field in self.fields:            rv[field] = getattr(self, field, None)        return rv    def update(self, **kwargs):        for field, value in kwargs.iteritems():            setattr(self, field, value)    def clear(self):        self.local_obj.__dict__.clear()    def __getattr__(self, name):        return getattr(self.local_obj, name, None)    def __setattr__(self, name, value):        if name in self.fields:            return setattr(self.local_obj, name, value)        else:            super(LocalManager, self).__setattr__(name, value)

创建本地线程变量
worker_local = LocalManager(_local) 仅仅这样用, 对于不同的线程, 其中的 worker_local不同

WorkerThread

WorkerThread :该类继承自 threading.Thread, 为具体线程的类

  • threading.Thread 特定用法:
    • 在构造函数中传入一个callable对象,(函数或者其他)
    • 在子类中重写 __init__run 方法
  • get_result(self) 方法类似与 requests.raise_for_status(): 先存异常状态码,再抛出异常
class WorkerThread(threading.Thread):    def __init__(self, func, *args, **kwargs):        super(WorkerThread, self).__init__()        self.func = func        self.args = args        self.kwargs = kwargs        self.exception = None        self.result = None        self.request_params = worker_local.to_dict()    def run(self):        worker_local.update(**self.request_params)        try:            self.result = self.func(*self.args, **self.kwargs)        except Exception as e:            self.exception = e            log_exception('worker', e)    def get_result(self):        if self.exception is not None:            raise self.exception        else:            return self.result

注意

  • 在python中对于真正的并行, 应当使用multiprocessing模块, fork多个进行来并行的执行, 因为python 全局解释器锁的存在, python的线程提供interleving交叉, 但是实际上是连续串行执行,这仅仅对于有I/O操作时有效.
  • Thread-local 保存了线程拥有的局部变量,实现了线程变量的隔离, 比较好的实现,可以参考werkzeug中Thread-local的实现, 可以支持协程之间的私有数据 werkzeug

Reference

深入理解Thread-local