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