Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python map()和imap()在gevent.pool.pool中是如何工作的?_Python_Gevent - Fatal编程技术网

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()方法不触发执行
  • 为什么
    Pool
    实例在map()触发执行后具有非零长度
我已经阅读了gevent-1.0中pool.py的源代码,但我不理解源代码如何将greenlet添加到变量self.greenlet,以及map()imap()之间的区别。在我的选项中,imap()只返回一个iterable对象,map()返回由imap()生成的greenlet列表

以下是gevent的pool.pymap()imap()的源代码:

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不会执行,因为您从未
加入它们-请参阅