Werkzeug库:local模块

Posted bad-robot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Werkzeug库:local模块相关的知识,希望对你有一定的参考价值。

1、协程greenlet

from greenlet import greenlet
from greenlet import getcurrent
def t1():
    print(12,getcurrent())
    gr2.switch()
    print(34,getcurrent())
    gr2.switch()
def t2():
    print(56,getcurrent())
    gr1.switch()
    print(78,getcurrent())

gr1 = greenlet(t1) #启动一个携程
gr2 = greenlet(t2)
gr1.switch()

  这里创建了两个greenlet协程对象,gr1和gr2,分别对应于函数test1()和test2()。使用greenlet对象的switch()方法,即可以切换协程。上例中,我们先调用”gr1.switch()”,函数test1()被执行,然后打印出”12″;接着由于”gr2.switch()”被调用,协程切换到函数test2(),打印出”56″;之后”gr1.switch()”又被调用,所以又切换到函数test1()。但注意,由于之前test1()已经执行到第5行,也就是”gr2.switch()”,所以切换回来后会继续往下执行,也就是打印”34″;现在函数test1()退出,同时程序退出。由于再没有”gr2.switch()”来切换至函数test2(),所以程序第11行”print 78″不会被执行。

  getcurrent()用来获取协程的id。

2、使用greenlet实现为每个协程开辟数据存储空间

2.1、为每个协程开辟数据存储空间

  源码:

from greenlet import getcurrent as get_ident
from greenlet import greenlet

# 释放Local类实例化对象local中该协程存储在local.__storage__中key为self.__ident_func__()的数据
def release_local(local):
    local.__release_local__()

class Local(object):

    __slots__ = (‘__storage__‘, ‘__ident_func__‘)

    def __init__(self):
        # 设置类Local的对象l的属性__storage__为空字典
        object.__setattr__(self, ‘__storage__‘, {})
        # 设置类Local的对象l的属性__ident_func__为get_ident方法,get_ident()可以获取协程的id号
        object.__setattr__(self, ‘__ident_func__‘, get_ident)

    # 将类Local对象l内所有协程的数据生成一个生成器返回
    def __iter__(self):
        return iter(self.__storage__.items())

    # 释放该协程中存储的数据空间
    def __release_local__(self):
        self.__storage__.pop(self.__ident_func__(), None)

    # 获取该协程中存储的key为name的数据
    def __getattr__(self, name):
        try:
            return self.__storage__[self.__ident_func__()][name]
        except KeyError:
            raise AttributeError(name)

    # 将name作为key,value作为value存入该协程中的数据空间中
    def __setattr__(self, name, value):
        ident = self.__ident_func__()
        storage = self.__storage__
        try:
            storage[ident][name] = value
        except KeyError:
            storage[ident] = {name: value}

    # 删除该协程中存储的key为name的数据
    def __delattr__(self, name):
        try:
            del self.__storage__[self.__ident_func__()][name]
        except KeyError:
            raise AttributeError(name)

l = Local()

def t1():
    # 将数据a=1 ,A=3存入协程gr1中
    l.a = 1
    l.A = 3
    print("携程a:%s" % get_ident(), l.a)
    gr2.switch()

def t2():
    # 将数据b=2 ,B=4存入协程gr2中
    l.b = 2
    l.B = 4
    print("携程b:%s" % get_ident(), l.b)
    gr1.switch()

# 将数据m=8 ,M=8存入默认生成的协程中(可以看做主协程)
l.m = 8
l.M = 8
print("携程m:%s" % get_ident(),l.m)
gr1 = greenlet(t1) #启动一个携程
gr2 = greenlet(t2)
gr1.switch()

print("携程m:%s" % get_ident(), l.m)
for k,v in l.__storage__.items():
    print("%s:%s"%(k,v))

  执行结果:

携程m:<greenlet.greenlet object at 0x01E25558> 8
携程a:<greenlet.greenlet object at 0x01E25500> 1
携程b:<greenlet.greenlet object at 0x01E25BE0> 2
携程m:<greenlet.greenlet object at 0x01E25558> 8
<greenlet.greenlet object at 0x01E25558>:{‘m‘: 8, ‘M‘: 8}
<greenlet.greenlet object at 0x01E25500>:{‘a‘: 1, ‘A‘: 3}
<greenlet.greenlet object at 0x01E25BE0>:{‘b‘: 2, ‘B‘: 4}

2.2、在协程执行完后释放数据存储空间

  源码:

from greenlet import getcurrent as get_ident
from greenlet import greenlet

# 释放Local类实例化对象local中该协程存储在local.__storage__中key为self.__ident_func__()的数据
def release_local(local):
    local.__release_local__()

class Local(object):

    __slots__ = (‘__storage__‘, ‘__ident_func__‘)

    def __init__(self):
        # 设置类Local的对象l的属性__storage__为空字典
        object.__setattr__(self, ‘__storage__‘, {})
        # 设置类Local的对象l的属性__ident_func__为get_ident方法,get_ident()可以获取协程的id号
        object.__setattr__(self, ‘__ident_func__‘, get_ident)

    # 将类Local对象l内所有协程的数据生成一个生成器返回
    def __iter__(self):
        return iter(self.__storage__.items())

    # 释放该协程中存储的数据空间
    def __release_local__(self):
        self.__storage__.pop(self.__ident_func__(), None)

    # 获取该协程中存储的key为name的数据
    def __getattr__(self, name):
        try:
            return self.__storage__[self.__ident_func__()][name]
        except KeyError:
            raise AttributeError(name)

    # 将name作为key,value作为value存入该协程中的数据空间中
    def __setattr__(self, name, value):
        ident = self.__ident_func__()
        storage = self.__storage__
        try:
            storage[ident][name] = value
        except KeyError:
            storage[ident] = {name: value}

    # 删除该协程中存储的key为name的数据
    def __delattr__(self, name):
        try:
            del self.__storage__[self.__ident_func__()][name]
        except KeyError:
            raise AttributeError(name)

l = Local()


def t1():
    l.a = 1
    l.A = 3
    print("携程a:%s" % get_ident(), l.a)
    gr2.switch()
    release_local(l)
    print("携程a:%s||是否有l.a:" % get_ident(), hasattr(l, ‘a‘))
    gr2.switch()

def t2():
    l.b = 2
    l.B = 4
    print("携程b:%s" % get_ident(), l.b)
    gr1.switch()
    release_local(l)
    print("携程b:%s||是否有l.b:" % get_ident(), hasattr(l, ‘b‘))


# 将数据m=8 ,M=8存入默认生成的协程中(可以看做主协程)
l.m = 8
l.M = 8
print("携程m:%s" % get_ident(),l.m)
gr1 = greenlet(t1) #启动一个携程
gr2 = greenlet(t2)
gr1.switch()

print("携程m:%s" % get_ident(), l.m)
for k,v in l.__storage__.items():
    print("%s:%s" % (k, v))

  执行结果:

携程m:<greenlet.greenlet object at 0x00635608> 8
携程a:<greenlet.greenlet object at 0x006355B0> 1
携程b:<greenlet.greenlet object at 0x00635558> 2
携程a:<greenlet.greenlet object at 0x006355B0>||是否有l.a: False
携程b:<greenlet.greenlet object at 0x00635558>||是否有l.b: False
携程m:<greenlet.greenlet object at 0x00635608> 8
<greenlet.greenlet object at 0x00635608>:{‘m‘: 8, ‘M‘: 8}

 

  

 

以上是关于Werkzeug库:local模块的主要内容,如果未能解决你的问题,请参考以下文章

Werkzeug之Local源码解析

flask 中的 werkzeug Local,LocalStack 和 LocalProxy 技术应用

werkzeug(flask)中的local,localstack,localproxy探究

Werkzeug之LocalStack源码解析

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

什么是Werkzeug