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}

  

原文地址:https://www.cnblogs.com/bad-robot/p/10079513.html

时间: 2024-10-06 00:53:57

Werkzeug库:local模块的相关文章

Werkzeug库——wrappers模块

Werkzeug库中的wrappers模块主要对request和response进行封装.request包含了客户端发往服务器的所有请求信息,response包含了web应用返回给客户端的所有信息.wrappers模块对请求和响应的封装简化了客户端.服务器和web应用通信的流程.本文主要介绍wrappers模块中重要的类. BaseRequest BaseRequest是一个非常基础的请求类,它可以和其他的"混合"类结合在一起构建复杂的请求类.只要传递一个环境变量environ(由WS

Werkzeug之Local源码解析

Werkzeug之Local源码解析 原博客地址 http://liuyajing.coding.me/blogs/python/2018/werkzeug-local/ 一.引入 最近在阅读 Flask 的源码,遇到三个概念:Local . LocalStack 和 LocalProxy ,本文主要就针对 Local 概念及其源码进行原理剖析. 二.Local Local 是一个类,源码位置:site-packages/werkzeug/local.py 在模块的开头,有以下代码: # 由于每

Python 安装第三方库,模块和包的安装方法

在python中已经内置了很多的有用的模块,只要安装了python的开发工具,这些模块就可以立刻使用了.而在实际python开发的过程中,除了python内置的模块外,python还有大量的第三方的库.模块和包. 常用的第三模块都会在python的PyPI - the Python Package Index上进行注册,只要找到对应模块的名字就可以进行安装了. 由于最近需要通过python来创建PDF文档,但是由于python的内置模块中相关的模块,所以需要使用第三方的reportlab库来创建

计算机职称考试题库Internet模块操作练习模拟试题(一)

1.请为当前计算机添加连接到com1口的标准56000 bps调制解调器设备,要求不检测当前连接设备. 当前界面:开始à控制面板 方法一: 打开[电话和调整解调器选项]à[调整解调器]选项卡à[添加]按钮à选中[不要检测我的调制解调器设备……]à下一步à型号:标准 56000 bps 调制解调器à下一步à选定的端口:com1à下一步à完成 方法二: 添加新硬件à下一步à选择[是,我已经连接了此硬件]à下一步à列表拉到最后选择[添加新的硬件设备]à下一步à选择[安装我手动从列表选择的硬件(高级)]

使用不同的C++支持库的模块混合开发时,引发异常展开不正常,抛异常竟引出一个SIGSEGV

如果你使用gcc对一部分模块进行了GNUMake的编译,这些编译出动态库使用在Gradle编译框架下的项目.那么就有可能出现题目中的情况,使用不同的C++支持库的模块混合开发时,引发异常展开不正常. 当我们使用GNUMake编译的项目进行移植编译时,都会使用Ndk的toolchains下对应的gcc进行编译,并且链接到对应的c++支持库.但是Gradle(或者说Android Studio)默认使用clang,并且执意链接到llvm对应的libc++支持库. 以我的情况为例子,我选用了Ice-3

Python 标准库 ConfigParser 模块 的使用

Python 标准库 ConfigParser 模块 的使用 demo #!/usr/bin/env python # coding=utf-8 import ConfigParser import sys config = ConfigParser.ConfigParser() #写入 config.add_section("Inc_basic") config.set("Inc_basic","name","iPIN")

mark LINUX_6.8 python_2.6.6 setup版本升级 python 2.7.9 安装 pip 临时使用国内镜像源库 指定模块版本 删除指定模块

简单但却又经常需要使用  网上  贴子也很多  也经常用  所以 做个mark 吧: 1首先下载python2.7.9 源tar包 源码安装 可利用linux自带下载工具wget下载,如下所示:    wget http://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz 下载完成后到下载目录下,解压   tar -zxvf Python-2.7.9.tgz 进入解压缩后的文件夹 cd ./Python-2.7.9 在编译前先在/usr/loca

[python标准库]XML模块

1.什么是XML XML是可扩展标记语言(Extensible Markup Language)的缩写,其中的 标记(markup)是关键部分.您可以创建内容,然后使用限定标记标记它,从而使每个单词.短语或块成为可识别.可分类的信息. XML有以下几个特点. XML的设计宗旨是传输数据,而非显示数据. XML标签没有被预定义.您需要自行定义标签. XML被设计为具有自我描述性. XML是W3C的推荐标准. 其解析流程如下图: 2.常用解析XML的Python包 Python的标准库中,提供了6种

我的简陋界面库的模块组成

目前界面不大,才几千行代码,所以我分割的也不是特别详细. 个人感觉,写这些东西,还是面向对象的思想比较好,所以,模块的组织方式,都是以面向对象的思想组织起来的. 我英语很差,没把这些玩意写成拼音,我很庆幸. 这套库现在的当务之急,就是寻找一个有效的同步或者互斥的方案,立刻修改为多线程安全版本,不然的话,以后修改的难度会大大增加. 从后往前说吧, window.h 窗口模块,所有和窗口有关的东西,都在它里面处理,当然了,凡是能看到的东西都是窗口,所以都在它里面处理, themeui.h 皮肤库模块