Python map()和imap()在gevent.pool.pool中是如何工作的?
我写了一个脚本来了解Python map()和imap()在gevent.pool.pool中是如何工作的?,python,gevent,Python,Gevent,我写了一个脚本来了解gevent.pool.pool,但我看到了一个奇怪的phonemenon 在我的代码中,我有三个不同的代码段,分别命名为版本1、版本2和版本3 当注释版本2和版本3时,即仅使用版本1中的imap()方法,则不会发生任何事情 在注释版本1和版本3时,即仅使用版本2中的map()方法,然后我发现第一个map()方法创建两个greenlet,然后执行两个greenlet。完成这两个greenles之后,第二个map()方法执行相同的操作 在注释版本1和版本2时,即首先使用ima
gevent.pool.pool
,但我看到了一个奇怪的phonemenon
在我的代码中,我有三个不同的代码段,分别命名为版本1、版本2和版本3
- 当注释版本2和版本3时,即仅使用版本1中的imap()方法,则不会发生任何事情李>
- 在注释版本1和版本3时,即仅使用版本2中的map()方法,然后我发现第一个map()方法创建两个greenlet,然后执行两个greenlet。完成这两个greenles之后,第二个map()方法执行相同的操作李>
- 在注释版本1和版本2时,即首先使用imap()方法,然后在版本3中使用map()方法,我发现在执行map()方法之前,会创建并执行五个小绿圈
- 为什么map()方法触发执行,而imap()方法不触发执行李>
- 为什么
实例在map()触发执行后具有非零长度Pool
def map(self, func, iterable):
return list(self.imap(func, iterable))
def imap(self, func, iterable):
"""An equivalent of itertools.imap()"""
return IMap.spawn(func, iterable, spawn=self.spawn)
以下是我的测试代码:
#!/usr/bin/env python2.7
#coding: utf-8
import gevent
from gevent.pool import Pool
from gevent.coros import BoundedSemaphore
class TestSemaphore(object):
def __init__(self):
self.sem = BoundedSemaphore(1)
self.pool = Pool()
def run(self):
# version 1
self.pool.imap(self._worker, xrange(0, 2))
self.pool.imap(self._worker, xrange(3, 6))
# end of version 1
# version 2
# self.pool.map(self._worker, xrange(0, 2))
# self.pool.map(self._worker, xrange(3, 6))
# end of version 2
# version 3
# self.pool.imap(self._worker, xrange(0, 2))
# self.pool.map(self._worker, xrange(3, 6))
# end of version 3
def _worker(self, pid):
with self.sem:
print('worker %d acquired semaphore, length of pool is %d' % (pid, len(self.pool)))
gevent.sleep(0)
print('worker %d released semaphore, length of pool is %d' % (pid, len(self.pool)))
if __name__ == '__main__':
test = TestSemaphore()
test.run()
需要注意的关键点是,
imap
是惰性的-在您实际使用生成的迭代器之前,它不会做任何工作:
>>> map(lamda x: x, xrange(0, 2))
[0, 1]
>>> from itertools import imap
>>> imap(lamda x: x, xrange(0, 2))
<generator object at 0xsome-address>
# Consume the resulting iterator
>>> list(imap(lamda x: x, xrange(0, 2)))
[0, 1]
地图(lamda x:x,xrange(0,2))
[0, 1]
>>>从itertools导入imap
>>>imap(lamda x:x,xrange(0,2))
#使用生成的迭代器
>>>列表(imap(lamda x:x,xrange(0,2)))
[0, 1]
imap
在multiprocessing
和gevent
中遵循相同的规则。池实例不是greenlet,在它将greenlet添加到自身后,池实例如何触发这些greenlet执行?这里是,greenlet不执行。@flyer:我看不出您的测试脚本与gevent.pool.pool.imap()
的使用有什么关系,它是在multiprocessing.pool.imap
之后建模的(一个在内置map()
之后建模的过于简单的接口),很抱歉我的表达不好。另一个测试脚本只显示池实例不是greenlet,并且其中的greenlet不会执行。这样,我想知道为什么map()会触发池实例中的greenlet来执行。@flyer-IMap
但是它是一个greenlet,map
调用IMap
,然后显式运行它(使用list
)。在引擎盖下,IMap
使用队列
并使用get
@flyer从队列中提取条目-在您的测试中,greenlet不会执行,因为您从未加入它们-请参阅