看,人。我们对gevent.pool类和pool.wait_available()方法有疑问,两个代码片段
1
def fetch(url):
print 'start fetching...', url
data = urllib2.urlopen(url)
print url,':',data.code
urls = ['http://www.google.ru', 'http://www.s-str.ru', 'http://www.vk.com', 'http://www.yandex.ru', 'http://www.xxx.com']
pool = Pool(2)
def producer():
for url in urls:
pool.spawn(fetch, url)
pool.join()
p = gevent.spawn(producer)
p.join()
2
def fetch(url):
print 'start fetching...', url
data = urllib2.urlopen(url)
print url,':',data.code
urls = ['http://www.google.ru', 'http://www.s-str.ru', 'http://www.vk.com', 'http://www.yandex.ru', 'http://www.xxx.com']
pool = Pool(2)
def producer():
for url in urls:
pool.wait_available()
pool.spawn(fetch, url)
pool.join()
p = gevent.spawn(producer)
p.join()
给我们类似的结果:
start fetching... http://www.google.ru
start fetching... http://www.s-str.ru
http://www.google.ru : 200
start fetching... http://www.vk.com
http://www.s-str.ru : 200
start fetching... http://www.yandex.ru
http://www.yandex.ru : 200
start fetching... http://www.xxx.com
http://www.vk.com : 200
http://www.xxx.com : 200
任何人都可以解释wait_available()方法的含义吗?以及它的使用情况。
=======更新======== 我已经猴子对它进行了操作,它工作正常,我只想知道 - 这是两个代码片段的区别。
答案 0 :(得分:2)
TL; DR :wait_available
是不必要的,因为在两种方法中都运行相同的检查。但是,如果您正在使用apply_async
并且想要不提交高于池上限的线程,那么您应首先致电wait_available
。
对于可能稍微更清楚的解释..有几种方法可以与gevent的Pool
类达成相同的目的。在池中使用spawn
将阻止,直到Pool
中有可用空间来运行新的greenlet。这是一个简单的例子:
import gevent.monkey
gevent.monkey.patch_all()
import gevent.pool
import time
def my_slow_function():
time.sleep(5)
def log(text):
print '%d : %s' % (int(time.time()), text)
if __name__ == '__main__':
thread_pool = gevent.pool.Pool(5)
for i in xrange(20):
log('Submitting slow func %d' % i)
thread_pool.spawn(my_slow_function)
thread_pool.join()
log('Exiting')
这个输出显示它会以5个为一组产生这些,因为池包含5个greenlet的空间:
1403037287:提交慢功能0
1403037287:提交慢功能1
1403037287:提交慢功能2
1403037287:提交慢功能3
1403037287:提交慢功能4
1403037292:提交慢功能5
1403037292:提交慢功能6
1403037292:提交慢功能7
1403037292:提交慢功能8
1403037292:提交慢功能9
1403037297:提交慢功能10
1403037297:提交慢功能11
1403037297:提交慢功能12
1403037297:提交慢功能13
1403037297:提交慢功能14
1403037302:提交慢功能15
1403037302:提交慢功能16
1403037302:提交慢功能17
1403037302:提交慢功能18
1403037302:提交慢功能19
1403037307:退出
正如你所看到的那样,它们以相隔大约5秒钟的5个小组的形式产生。如果您深入了解gevent代码并查看Pool对象,您可以看到调用spawn
将要求锁定Pool
用于跟踪运行greenlet的内部信号量。
相反,如果您使用apply_async
而不是spawn
尝试使用相同的代码,则会强制所有调用同时运行:
1403037313:提交慢功能0
1403037313:提交慢功能1
1403037313:提交慢功能2
1403037313:提交慢功能3
1403037313:提交慢功能4
1403037313:提交慢功能5
1403037313:提交慢功能6
1403037313:提交慢功能7
1403037313:提交慢功能8
1403037313:提交慢功能9
1403037313:提交慢功能10
1403037313:提交慢功能11
1403037313:提交慢功能12
1403037313:提交慢功能13
1403037313:提交慢功能14
1403037313:提交慢功能15
1403037313:提交慢功能16
1403037313:提交慢功能17
1403037313:提交慢功能18
1403037313:提交慢功能19
1403037318:退出
你可以在这里看到没有阻挡或等待,他们同时被推入。但是,如果您在for循环的开头引入wait_available()
,则会返回到与spawn
类似的行为。
1403038292:提交慢功能0
1403038292:提交慢功能1
1403038292:提交慢功能2
1403038292:提交慢功能3
1403038292:提交慢功能4
1403038297:提交慢功能5
1403038297:提交慢功能6
1403038297:提交慢功能7
1403038297:提交慢功能8
1403038297:提交慢功能9
1403038302:提交慢功能10
1403038302:提交慢功能11
1403038302:提交慢功能12
1403038302:提交慢功能13
1403038302:提交慢功能14
1403038307:提交慢功能15
1403038307:提交慢功能16
1403038307:提交慢功能17
1403038307:提交慢功能18
1403038307:提交慢功能19
1403038312:退出
再一次,查看gevent中的来源,wait_available
执行与调用spawn
相同的检查,{{1}}正在检查信号量以查看是否实际存在空间在游泳池里。
答案 1 :(得分:0)
使用gevent
,您需要先修补标准模块。
>>> import gevent.monkey
>>> gevent.monkey.patch_all()
>>> ...
>>> p = gevent.spawn(producer)
>>> p.join()
start fetching... http://www.google.ru
start fetching... http://www.s-str.ru
http://www.google.ru : 200
start fetching... http://www.vk.com
http://www.vk.com : 200
start fetching... http://www.yandex.ru
http://www.yandex.ru : 200
start fetching... http://www.xxx.com
http://www.xxx.com : 200
http://www.s-str.ru : 200
您可以看到,pool.wait_available()
可以预测。
<强>更新强>
Pool
仅以spawn
函数的相同方式工作(它将等待池中的可用“插槽”)。如果您需要提供基于Pool
状态(日志记录,跟踪,监控)的其他功能 - 您肯定会使用wait_available
,free_count
等功能。如果您只需要{{1新的绿色线程 - 你可以依靠spawn
实现。