Python的线程隔离实现方法

Posted 有虫子啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python的线程隔离实现方法相关的知识,希望对你有一定的参考价值。

 前段时间看了下flask的源码,对于这样一个轻量级的web框架是怎样支持多线程的感到非常好奇,于是深入了解了一番。

flask是依赖werkeug来实现线程间的隔离的,而werkeug最后又使用到了python的内置模块locals来承载数据,看不如写,于是自己实现了一下。

from threading import currentThread, Thread
from collections import defaultdict

import sys


class LocalProxy(object):

    def __init__(self):
        self.local = defaultdict(dict)

    def __repr__(self):
        return str(self.local)

    def __str__(self):
        return str(self.local)

    def __getitem__(self, item):
        return self.local[currentThread().ident][item]

    def __setitem__(self, key, value):
        self.local[currentThread().ident].update({key: value})

print(sys.version)
local_proxy = LocalProxy()
print(local_proxy)

local_proxy["main"] = "start"

def change_property():
    local_proxy["main"] = "end"

change_thread = Thread(target=change_property)
change_thread.daemon= True
change_thread.start()

change_thread.join()

print(local_proxy)

输出:

3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]
defaultdict(<class dict>, {})
defaultdict(<class dict>, {7092: {main: start}, 4892: {main: end}})

这里是使用locals来作为数据承载的dict,然后使用currentThread方法获取当前线程id,以此作为key来实现各线程间的数据隔离。

从输出可以看出,主线程设置了`main=start`后,子线程对该属性进行修改并未成功,而是在自己的线程id下创建了新的属性。

实现过程中还发生了一个小插曲,当时的开启线程代码如下:

change_thread = Thread(change_property)
change_thread.daemon= True
change_thread.start()

报错:

Traceback (most recent call last):
3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]
defaultdict(<class dict>, {})
  File "E:/project/blog/blog/src/utils/local_.py", line 34, in <module>
    change_thread = Thread(change_property)
  File "D:UsersAdministratorAnaconda3lib	hreading.py", line 781, in __init__
    assert group is None, "group argument must be None for now"
AssertionError: group argument must be None for now

于是点开Thread源码看看这个group为何物:

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):
        """This constructor should always be called with keyword arguments. Arguments are:

        *group* should be None; reserved for future extension when a ThreadGroup
        class is implemented.

原来Thread的初始化增加了group参数,切对其进行了断言,为以后即将实现的ThreadGroup铺路。

ps: 以后传参还是尽量带上参数名。

以上是关于Python的线程隔离实现方法的主要内容,如果未能解决你的问题,请参考以下文章

python threading超线程使用简单范例的代码

springboot隔离@Async异步任务的线程池

Python并发编程之线程中的信息隔离

Python编程之线程中的信息隔离!这才叫Python!

Flask的请求上下文机制

线程池-实现一个取消选项