zoukankan      html  css  js  c++  java
  • 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'}})

    这里是使用defaultdcit代替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: 以后传参还是尽量带上参数名。

  • 相关阅读:
    asp.net 生成PDF方法
    C# 缓存学习总结
    C# 缓存学习第一天
    C# 文件管理类 Directory
    C# 链接Sql和Access数据库语句
    SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn(实战篇)之AlwaysOn可用性组搭建
    SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn(实战篇)之建立活动目录域、DNS服务器和Windows故障转移群集(准备工作)
    SQL Server ->> 高可用与灾难恢复(HADR)技术 -- AlwaysOn可用性组(理论篇)
    SQL Server ->> 利用CONVERT/STR/FORMAT函数把浮点型数据格式化/转换成字符串
    SQL Server ->> Computed Column(计算列)
  • 原文地址:https://www.cnblogs.com/xu-xiaofeng/p/13349312.html
Copyright © 2011-2022 走看看