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]}