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″不会被执行。python
getcurrent()用来获取协程的id。app
源码:ide
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}
源码:线程
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}
Python3 线程中经常使用的两个模块为:对象
thread 模块已被废弃。用户可使用 threading 模块代替。因此,在 Python3 中不能再使用"thread" 模块。为了兼容性,Python3 将 thread 重命名为 "_thread"。blog
源码:get
import _thread from _thread import get_ident from time import sleep def run(n): print("子线程:%s --id: %s"%(n,get_ident())) def main(): _thread.start_new_thread(run, ("t1",)) _thread.start_new_thread(run, ("t2",)) if __name__ == "__main__": main() sleep(2) print("主线程 --id: %s" % ( get_ident()))
执行结果:源码
子线程:t2 --id: 5452 子线程:t1 --id: 10488 主线程 --id: 9804
源码:
from _thread import get_ident,start_new_thread from time import sleep # 释放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存入当前线程中 l.a = 1 l.A = 3 print("线程a:%s" % get_ident(), l.a) print("l.__storage__:",l.__storage__) def t2(): # 将数据b=2 ,B=4存入当前线程中 l.b = 2 l.B = 4 print("线程b:%s" % get_ident(), l.b) print("l.__storage__:",l.__storage__) def main(): # 将数据m=8 ,M=8存入默认生成的线程中(能够看作主线程) print("l.__storage__:", l.__storage__) l.m = 8 l.M = 8 print("l.__storage__:", l.__storage__) print("线程m:%s" % get_ident(),l.m) start_new_thread(t1, ()) start_new_thread(t2, ()) sleep(5) print("线程m:%s" % get_ident(), l.m) print("l.__storage__:", l.__storage__) if __name__ == "__main__": main()
执行结果:
l.__storage__: {} l.__storage__: {12548: {'m': 8, 'M': 8}} 线程m:12548 8 线程a:10656 1 l.__storage__: {12548: {'m': 8, 'M': 8}, 10656: {'a': 1, 'A': 3}} 线程b:11564 2 l.__storage__: {12548: {'m': 8, 'M': 8}, 10656: {'a': 1, 'A': 3}, 11564: {'b': 2, 'B': 4}} 线程m:12548 8 l.__storage__: {12548: {'m': 8, 'M': 8}, 10656: {'a': 1, 'A': 3}, 11564: {'b': 2, 'B': 4}}
源码:
from _thread import get_ident,start_new_thread from time import sleep # 释放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存入当前线程中 l.a = 1 l.A = 3 print("线程a:%s" % get_ident(), l.a) print("l.__storage__:",l.__storage__) release_local(l) print("释放后l.__storage__:",l.__storage__) def t2(): # 将数据b=2 ,B=4存入当前线程中 l.b = 2 l.B = 4 print("线程b:%s" % get_ident(), l.b) print("l.__storage__:",l.__storage__) release_local(l) print("释放后l.__storage__:", l.__storage__) def main(): # 将数据m=8 ,M=8存入默认生成的线程中(能够看作主线程) print("l.__storage__:", l.__storage__) l.m = 8 l.M = 8 print("l.__storage__:", l.__storage__) print("线程m:%s" % get_ident(),l.m) start_new_thread(t1, ()) start_new_thread(t2, ()) sleep(5) print("线程m:%s" % get_ident(), l.m) print("l.__storage__:", l.__storage__) if __name__ == "__main__": main()
执行结果:
l.__storage__: {} l.__storage__: {11480: {'m': 8, 'M': 8}} 线程m:11480 8 线程b:12560 2 l.__storage__: {11480: {'m': 8, 'M': 8}, 12560: {'b': 2, 'B': 4}} 释放后l.__storage__: {11480: {'m': 8, 'M': 8}} 线程a:7628 1 l.__storage__: {11480: {'m': 8, 'M': 8}, 7628: {'a': 1, 'A': 3}} 释放后l.__storage__: {11480: {'m': 8, 'M': 8}} 线程m:11480 8 l.__storage__: {11480: {'m': 8, 'M': 8}}
LocalStack中封装了Local对象。LocalStack用来管理Locall对象,并提供push,pop方法,用来在当前线程或协程中存储数据、提取数据。
class LocalStack(object): """This class works similar to a :class:`Local` but keeps a stack of objects instead. This is best explained with an example:: >>> ls = LocalStack() >>> ls.push(42) >>> ls.top 42 >>> ls.push(23) >>> ls.top 23 >>> ls.pop() 23 >>> ls.top 42 They can be force released by using a :class:`LocalManager` or with the :func:`release_local` function but the correct way is to pop the item from the stack after using. When the stack is empty it will no longer be bound to the current context (and as such released). By calling the stack without arguments it returns a proxy that resolves to the topmost item on the stack. .. versionadded:: 0.6.1 """ def __init__(self): # 实例化一个Local()对象 self._local = Local() # 释放当前线程或协程的数据存储空间 def __release_local__(self): self._local.__release_local__() # 获取当前线程或协程的__ident_func__属性 def _get__ident_func__(self): return self._local.__ident_func__ # 设置当前线程或协程的__ident_func__属性 def _set__ident_func__(self, value): object.__setattr__(self._local, '__ident_func__', value) __ident_func__ = property(_get__ident_func__, _set__ident_func__) del _get__ident_func__, _set__ident_func__ def __call__(self): def _lookup(): rv = self.top if rv is None: raise RuntimeError('object unbound') return rv return LocalProxy(_lookup) # 将obj存入当前线程或协程的数据存储空间中以stack做为key的字典中 def push(self, obj): """Pushes a new item to the stack""" rv = getattr(self._local, 'stack', None) if rv is None: self._local.stack = rv = [] rv.append(obj) return rv # 对当前线程或协程的数据存储空间将以stack做为key的字典pop出一个数据, # 若是总数据长度为1,释放线程或协程的数据存储空间 def pop(self): """Removes the topmost item from the stack, will return the old value or `None` if the stack was already empty. """ stack = getattr(self._local, 'stack', None) if stack is None: return None elif len(stack) == 1: release_local(self._local) return stack[-1] else: return stack.pop() # 对当前线程或协程的数据存储空间将以stack做为key的字典中最顶端的数据 @property def top(self): """The topmost item on the stack. If the stack is empty, `None` is returned. """ try: return self._local.stack[-1] except (AttributeError, IndexError): return None
源码:
from greenlet import greenlet from werkzeug.local import LocalStack ls = LocalStack() # 打印ls._local中存储的数据 def get_datas(ls): for k, v in ls._local: print("%s:%s" % (k, v)) def t1(): # 将数据1, 3存入协程gr1中 ls.push(1) ls.push(3) print("协程gr1添加后:") get_datas(ls) gr2.switch() ret = ls.pop() print("协程gr1释放:%s"%ret) print("协程gr1释放后:") get_datas(ls) print("协程gr1获取top:",ls.top) gr2.switch() def t2(): # 将数据2, 4存入协程gr2中 ls.push(2) ls.push(4) print("gr2添加后:") get_datas(ls) gr1.switch() ret = ls.pop() print("协程gr2释放:%s" % ret) print("协程gr2释放后:") get_datas(ls) print("协程gr2获取top:", ls.top) # 将数据8, 8存入默认生成的协程中(能够看作主协程) ls.push(8) ls.push(18) print("协程m添加后:") get_datas(ls) gr1 = greenlet(t1) #启动一个协程 gr2 = greenlet(t2) gr1.switch() print("协程m:") get_datas(ls)
执行结果:
协程m添加后: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} 协程gr1添加后: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} <greenlet.greenlet object at 0x005DF298>:{'stack': [1, 3]} gr2添加后: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} <greenlet.greenlet object at 0x005DF298>:{'stack': [1, 3]} <greenlet.greenlet object at 0x0061F1E8>:{'stack': [2, 4]} 协程gr1释放:3 协程gr1释放后: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} <greenlet.greenlet object at 0x005DF298>:{'stack': [1]} <greenlet.greenlet object at 0x0061F1E8>:{'stack': [2, 4]} 协程gr1获取top: 1 协程gr2释放:4 协程gr2释放后: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} <greenlet.greenlet object at 0x005DF298>:{'stack': [1]} <greenlet.greenlet object at 0x0061F1E8>:{'stack': [2]} 协程gr2获取top: 2 协程m: <greenlet.greenlet object at 0x005D4A28>:{'stack': [8, 18]} <greenlet.greenlet object at 0x005DF298>:{'stack': [1]} <greenlet.greenlet object at 0x0061F1E8>:{'stack': [2]}