https://greenlet.readthedocs.io/en/latest/ Motivation The “greenlet” package is a spin-off of Stackless and the greenlet is “dead”. Every greenlet has a “parent” greenlet. Instantiation greenlet.greenlet is the greenlet type, which supports the following operations: greenlet , and parent is the parent greenlet, which defaults to the current greenlet.
greenlet好像是stackless的副产品,是python的一个扩展模块。它的使用与stackless不太一样。 根据自己对stackless的理解,编写了glstackless.py模块。 压缩包里面还有一个stackless.py文件,这个是pypy包提供的用greenlet模拟stacklee的单元。 我这才发现原来greenlet使用不当,也会出现这中递归调用超出最大值的问题。glstackless针对这个问题,使用一个独立的tasklet来解决,具体是GLMgr.looptask。
2核2G云服务器 每月9.33元起,个人开发者专属3年机 低至2.3折
greenlet示例 greenlet微线程,允许在线程中手动切换 示例1,线程切换 from greenlet import greenlet def test1(x,y): z = gr2. switch(x+y) print(z) def test2(u): print(u) gr1.switch(42) gr1 = greenlet(test1) gr2 = greenlet (test2) gr1.switch("hello",'world') gr1和gr2是两个greenlet线程,使用gr1.switch(..)启动gr1,gr1执行test1,切换到gr2,gr2执行 import greenlet def eat(name): print('%s eat 1' %name) g2.switch('egon') print('%s eat 2' %name ,以后都不需要 gevent gevent基于greenlet,遇到IO操作自动切换,IO操作比如网络请求,或使用 gevent.sleep(0)强制切换.
都无法实现,就用到了gevent模块(select机制)) Greenlet模块 安装方法 windows下 cmd 在命令行执行 pip3 install greenlet greenlet实现状态切换 from greenlet import greenlet # 不是创造协程的模块 # 在协程这个模块中用来做多个协程任务的切换问题的 # 它到底是怎样实现切换的呢? Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。 # 初始化的greenlet列表存放在数组threads中,此数组被传给gevent.joinall 函数, # 后者阻塞当前流程,并执行所有给定的greenlet任务。 执行流程只会在 所有greenlet执行完后才会继续向下走。 执行结果 ?
其实本来不想卸这些说不定哪天还有用的包…… 但pyinstaller运行时报错提示greenlet库有问题,不卸载就无法成功运行。 尝试了更新greenlet,但pyinstaller打包程序时依然报greenlet的错_(:з」∠)_尝试了用conda uninstall greenlet和pip uninstall greenlet 还有个办法是找到greenlet所在的文件夹(cmd输入pip show package greenlet可以看),我的是在D:\Anaconda3\Lib\site-packages下的gevent文件夹 ,找到文件夹后,把文件夹改名,比如gevent_old,就OK了~楼主这边运行pyinstaller不会再因为greenlet报错了。
greenlet模块 为了更好使用协程来完成多任务,python 中的 greenlet 模块对其封装,从而使得切换任务变的更加简单 使用如下命令安装 greenlet 模块: pip install greenlet 代码演示 import time from greenlet import greenlet def task1(): while True: print : fun(5)> 0 <Greenlet at 0x25218679a68: fun(5)> 1 <Greenlet at 0x25218679a68: fun(5)> 2 <Greenlet at <Greenlet at 0x25218679b88: fun(5)> 1 <Greenlet at 0x25218679b88: fun(5)> 2 <Greenlet at 0x25218679b88 : fun(5)> 1 <Greenlet at 0x162030284c8: fun(5)> 2 <Greenlet at 0x16203028a68: fun(5)> 2 <Greenlet at
三、使用greenlet实现任务切换 安装greenlet: pip install greenlet import greenlet import time def greenlet1 (greenlet1) g2 = greenlet.greenlet(greenlet2) # 切换到gr1中运行 g1.switch() 运行结果: -----greenlet1- ---- -----greenlet2----- -----greenlet1----- -----greenlet2----- -----greenlet1----- -----greenlet2 上面的代码中,我们写了两个函数greenlet1和greenlet2,在greenlet1中的代码执行完成后,通过switch()切换到greenlet2,greenlet2中的代码执行完成后,又通过switch 这样就实现了任务的切换,我们要调用两个任务,只需要在主线程中先切换到greenlet1,程序就会在greenlet1和greenlet2之间来回切换执行。
为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单 from greenlet import greenlet import time (5)> 2 <Greenlet at 0x7f688ad95748: test(5)> 3 <Greenlet at 0x7f688ad95748: test(5)> 4 <Greenlet at 0x7f688ad95948 : test(5)> 0 <Greenlet at 0x7f688ad95948: test(5)> 1 <Greenlet at 0x7f688ad95948: test(5)> 2 <Greenlet (5)> 0 <Greenlet at 0x7f688ad95a48: test(5)> 1 <Greenlet at 0x7f688ad95a48: test(5)> 2 <Greenlet at 0x7f688ad95a48 : test(5)> 1 <Greenlet at 0x7fe357a77748: test(5)> 2 <Greenlet at 0x7fe357a77948: test(5)> 2 <Greenlet
greenlet File "/work/greenlet.py", line 3, in <module> from greenlet import greenlet ImportError "Greenlet-0" at 0x7fef6badfcb0: f(5)>, 1) (<Greenlet "Greenlet-0" at 0x7fef6badfcb0: f(5)>, 2) (<Greenlet <Greenlet "Greenlet-1" at 0x7f0db293bdb8: f(5)>, 0) (<Greenlet "Greenlet-2" at 0x7f0db293bec0: f(5)>, 0) (<Greenlet "Greenlet-0" at 0x7f0db293bcb0: f(5)>, 1) (<Greenlet "Greenlet-1" at 0x7f0db293bdb8: f (5)>, 1) (<Greenlet "Greenlet-2" at 0x7f0db293bec0: f(5)>, 1) (<Greenlet "Greenlet-0" at 0x7f0db293bcb0
三、greenlet 1、greenlet实现多任务协程 为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单,在使用前先要确保greenlet模块安装 使用如下命令安装greenlet模块: sudo pip install greenlet #coding = utf-8 from greenlet import greenlet def test1 2、greenlet的模块与类 我们首先看一下greenlet这个module里面的属性 >>> import greenlet >>> dir(greenlet) ['GREENLET_USE_GC' ) 然后我们再来看看greenlet.greenlet这个类: >>>dir(greenlet.greenlet) ['GreenletExit', '__bool__', '__class__', ' ,后面介绍 dead:如果greenlet执行结束,那么该属性为true throw:切换到指定greenlet后立即跑出异常 文章后面提到的greenlet大多都是指greenlet.greenlet
"Greenlet-0" at 0x26d8c970488: work(5)> 0 <Greenlet "Greenlet-1" at 0x26d8c970598: work(5)> 0 <Greenlet "Greenlet-2" at 0x26d8c9706a8: work(5)> 0 <Greenlet "Greenlet-0" at 0x26d8c970488: work(5)> 1 <Greenlet "Greenlet-1" at 0x26d8c970598: work(5)> 1 <Greenlet "Greenlet-2" at 0x26d8c9706a8: work(5)> 1 <Greenlet "Greenlet-0" at 0x26d8c970488: work(5)> 2 <Greenlet "Greenlet-1" at 0x26d8c970598: work(5)> 2 <Greenlet "Greenlet-2" at 0x26d8c9706a8: work(5)> 2 <Greenlet "Greenlet-0" at 0x26d8c970488: work(5)> 3 <Greenlet
协程本质是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程 二.协程的应用 1.greenlet模块 创建协程 g = greenlet.greenlet(方法) 只定义不执行 如果需要传参传参 在执行中进行传参 g = switch(参数) 且switch这个函数是个阻塞函数,如果上述进程没有进行完毕不会往下运行下去,switch还会命令该协程执行 如果再方法中有switch如下 from greenlet import greenlet def test1(): print (12) gr2.switch () #切换到g2且保留gr1的运行状态 print (34) def test2 (): print (56) gr1.switch() #切换到gr1的协程且不是从头开始,而是从gr1保存的运行状态那里接着执行 print (78) gr1 = greenlet (test1) gr2 = greenlet(test2) gr1.switch() ''' 12 56 34 ''' 2.gevent模块 使用 from gevent import monkey monkey.patch_all
实现协程:不是python自带模块,需要安装 创建协程对象的方法其实有两个参数”greenlet(run=None, parent=None)”。 参数”run”就是其要调用的方法,比如上例中的函数test1()和test2();参数”parent”定义了该协程对象的父协程,也就是说,greenlet协程之间是可以有父子关系的。 from greenlet import greenlet def test1(): print(1) t2.switch() # 函数暂停,切换到t2 print(2) def test2(): print(3) t1.switch() # 函数暂停,切换到t1 print(4) t1=greenlet(test1) # test1 生成greenlet对象 t2=greenlet(test2) # test2生成greenlet对象 t1.switch() 使用gevent实现协程:第三方库,需要安装 实现了异步I/O,操作
_gevent_c_greenlet_primitives.SwitchOutGreenletWithLoop.switch File "src/gevent/_greenlet_primitives.py _gevent_c_greenlet_primitives.SwitchOutGreenletWithLoop.switch File "src/gevent/_greenlet_primitives.py 它是基于 greenlet 实现的。greenlet 也可以理解为协程,就像 golang 里的 goroutine。 每个 greenlet 都会在一个线程上,一个线程上可以有多个 greenlet,但一次只有一个 greenlet 在运行。 对于每个协程,都需要在一个 hub 里运行,hub 被翻译为集线器,hub 也是一个 greenlet,为什么又要搞个 greenlet 呢,因为它是帮我们做切换调用栈的家伙。
python中实现协程是基于Gevent模块,Gevent模块内部封装了greenlet模块;greenlet模块实现了在单线程中切换状态,Gevent模块在此之上还实现了遇到I/O操作自动切换,使程序运行更快 Greenlet与Gevent模块都是python的第三方模块,需安装使用。 1、Greenlet 主要方法: g = greenlet(run=None, parent=None):实例化一个greenlet对象 g.parent:每一个协程都有一个父协程,当前协程结束后会回到父协程中执行 import greenlet def work(): print("1") g2.switch() # 切换到g2协程 print("3") g2.switch() def work2(): print("2") g1.switch() print("4") g1 = greenlet(work) # 创建一个greenlet实例 g2
main__': con1 = consumer("consumerA") con2 = consumer("consumerB") producer(con1, con2) 2.greenlet 实现协程 greenlet进行手动切换实现协程,切换的方式是switch from greenlet import greenlet import time def producer(): while consumer(): while 1: print('使用一件商品') time.sleep(0.5) g1.switch() g1 = greenlet (producer) #创建协程g1 g2 = greenlet(consumer) g1.switch() 3.Gevent实现协程 Gevent是一种基于协程的Python网络库,它用到Greenlet
都无法实现, 就用到了gevent模块(select机制) Greenlet模块 pip install greenlet from greenlet import greenlet def eat( (f1) g2=greenlet(f2) g1.switch() stop=time.time() print('run time is %s' %(stop-start)) greenlet只是提供了一种比 Greenlet全部运行在主程序操作系统进 程的内部,但它们被协作式地调度。 # 初始化的greenlet列表存放在数组threads中,此数组被传给gevent.joinall 函数, # 后者阻塞当前流程,并执行所有给定的greenlet任务。 执行流程只会在 所有greenlet执行完后才会继续向下走。
2.2 greenlet实现协程 Python的 greenlet就相当于手动切换,去执行别的子程序,在“别的子程序”中又主动切换回来。。。 greenlet协程例子: 1 #! /usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 from greenlet import greenlet 5 # greenlet 其实就是手动切换 是一个第三方库,可以轻松通过gevent实现协程程,在gevent中用到的主要模式是Greenlet, 它是以C扩展模块形式接入Python的轻量级协程。 初始化的greenlet列表存放在数组threads中,此数组被传给gevent.joinall 函数,后者阻塞当前流程,并执行所有给定的greenlet。 执行流程只会在 所有greenlet执行完后才会继续向下走。 遇到Io阻塞时会切换任务之【爬虫版】 1 #!
解决办法就是使用 uWSGI 提供的异步切换引擎,比如说 greenlet —— uWSGI 会在单独的微线程中来执行每一个 application 函数。 其实,这里使用 greenlet 并不影响我们实现一个纯粹的 asyncio 异步 WSGI 服务器,只要写一个简单的函数包装一下就好了。 默认的 uWSGI 貌似并不包含 asyncio 和 greenlet 的支持,所以我们得亲自编译一份。 (venv) $ uwsgi --asyncio 512 -s /tmp/uwsgi.sock --greenlet -w your_package.uwsgi 其中呢,CFLAGS 指定 greenlet 的头文件目前是必须的(路径可能有出入),除非你的 greenlet 安装在系统库中。
扫码关注腾讯云开发者
领取腾讯云代金券