我是异步编程的新手,并且遵循Bottlepy-gevent教程here。
我运行了页面上给出的程序:
from gevent import monkey; monkey.patch_all()
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
yield 'START'
sleep(3)
yield 'MIDDLE'
sleep(5)
yield 'END'
run(host='0.0.0.0', port=8080, server='gevent')
并且当我访问网址http://localhost:8080/stream
,打印START
后跟MIDDLE
和END
时,它分别以3和5秒的休眠间隔运行。< / p>
根据文档,
monkey patching使gevent能够阻止Python的阻塞API(和 阻塞当前线程的函数,如time.sleep()), 并将CPU传递给下一个greenlet。
但是,当我修改上面的代码以打印当前的greenlet信息时,我得到了用于所有三个yield
语句的相同greenlet实例。
import gevent
from gevent import monkey
monkey.patch_all()
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
print(gevent.getcurrent())
yield 'START '
sleep(3)
print(gevent.getcurrent())
yield 'MIDDLE '
sleep(5)
print(gevent.getcurrent())
yield 'END'
run(host='0.0.0.0', port=8080, server='gevent')
控制台输出:
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
<Greenlet at 0x7f9fd733a9c8: _handle_and_close_when_done(<bound method WSGIServer.handle of <WSGIServer at , <bound method StreamServer.do_close of <WSGIServer, (<gevent._socket3.socket object, fd=7, family=2, t)>
根据瓶装文档,每次执行time.sleep()时都不应生成新的greenlet实例吗?
此外,当我运行类似的程序而不使用gevent和monkey-patching时,如下所示:
from time import sleep
from bottle import route, run
@route('/stream')
def stream():
yield 'START \n'
sleep(3)
yield 'MIDDLE \n'
sleep(5)
yield 'END'
run(host='0.0.0.0', port=8080)
我得到了与以前相同的回复(START跟随MIDDLE和END 3和5秒),与Bottlepy文档的评论相反,下面用粗体字表示:
如果您运行此脚本并将浏览器指向 http://localhost:8080/stream,您应该看到START,MIDDLE和END 一个接一个地出现(而不是等待8秒才能看到它们 一旦)。
我在这里错过了什么吗?
答案 0 :(得分:0)
注意强>: 某些浏览器在开始呈现页面之前会缓冲一定数量的数据。您可能需要产生多个字节才能在这些浏览器中看到效果。此外,许多浏览器每个URL限制一个并发连接。如果是这种情况,您可以使用第二个浏览器或基准工具(例如ab或httperf)来衡量性能。
答案 1 :(得分:0)
根据瓶装文档,每次执行time.sleep()时都不应该生成新的greenlet实例吗?
没有。那瓶文件有点令人困惑,我很害怕。
为每个传入的HTTP请求生成一个新的greenlet。生成的greenlet然后从头到尾处理整个请求。如果该greenlet(显式或隐式)产生,那么另一个greenlet可以自由地做一些工作(可能是处理其他一些HTTP请求)。
当你调用monkeypatched time.sleep
时,处理你的HTTP请求的greenlet被挂起,从而产生任何其他活动的greenlet(如果有的话)。当time.sleep
返回时(在指定的秒数之后),您的greenlet(之前为您的请求提供服务的那个)将被唤醒,并在sleep
调用之后恢复运行。
希望有所帮助!