gevent.pool.Pool中的map()和imap()如何工作?

fly*_*yer 4 python gevent

我写了一个脚本来学习gevent.pool.Pool,但是我看到了一个奇怪的语音提示。

在我的代码中,我有三个不同的代码段,分别是版本1版本2版本3

  • 当注释掉版本2版本3时,即仅在版本1中使用imap()方法时,则没有任何反应。
  • 当注释掉版本1版本3时,即仅使用版本2中map()方法时,我发现第一个map()方法创建了两个greenlet,然后执行了两个greenlet。完成这两个步骤后,第二个map()方法执行相同的操作。
  • 当注释掉版本1版本2时,即首先使用imap()方法,然后在版本3中使用map()方法时,我发现直到执行了map()方法,然后创建并执行了五个greenlet。

所以我有两个问题:

  • 为什么map()方法触发执行而imap()没有触发?
  • 为什么map()触发执行Pool后实例的长度为非零?

我读的源代码pool.py在GEVENT-1.0,但我不明白的源代码如何增加greenlets给变量self.greenlets之间的差异图()IMAP)( 。在我的选择中,imap()仅返回可迭代的对象,而map()返回由imap()生成的greenlets列表。

下面是源代码的地图()IMAP()pool.py GEVENT的:

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)
Run Code Online (Sandbox Code Playgroud)

这是我的测试代码:

#!/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()
Run Code Online (Sandbox Code Playgroud)

Sea*_*ira 5

需要注意的关键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]
Run Code Online (Sandbox Code Playgroud)

imapmultiprocessinggevent附着在相同的规则。