python中两个常用来处理进程的模块分别是subprocess和multiprocessing,其中subprocess通常用于执行外部程序,比如一些第三方应用程序,而不是Python程序。如果需要实现调用外部程序的功能,python的psutil模块是更好的选择,它不仅支持subprocess提供的功能,而且还能对当前主机或者启动的外部程序进行监控,比如获取网络、cpu、内存等信息使用情况,在做一些自动化运维工作时支持的更加全面。multiprocessing是python的多进程模块,主要通过启动python进程,调用target回调函数来处理任务,与之对应的是python的多线程模块threading,它们拥有类似的接口,通过定义multiprocessing.Process、threading.Thread,指定target方法,调用start()运行进程或者线程。

  在python中由于全局解释锁(GIL)的存在,使用多线程,并不能大大提高程序的运行效率【1】。因此,用python处理并发问题时,尽量使用多进程而非多线程。并发编程中,最简单的模式是,主进程等待任务,当有新任务到来时,启动一个新的进程来处理当前任务。这种每个任务一个进程的处理方式,每处理一个任务都会伴随着一个进程的创建、运行、销毁,如果进程的运行时间越短,创建和销毁的时间所占的比重就越大,显然,我们应该尽量避免创建和销毁进程本身的额外开销,提高进程的运行效率。我们可以用进程池来减少进程的创建和开销,提高进程对象的复用。

  实际上,python中已经实现了一个功能强大的进程池(multiprocessing.Pool),这里我们来简单剖析下python自带的进程池是如何实现的。


  要创建进程池对象,需要调用Pool函数,函数的声明如下:

Pool(processes=None, initializer=None, initargs=(), maxtasksperchild=None)
Returns a process pool object
processes表示工作进程的个数,默认为None,表示worker进程数为cpu_count()
initializer表示工作进程start时调用的初始化函数,initargs表示initializer函数的参数,如果initializer不为None,在每个工作进程start之前会调用initializer(*initargs)
maxtaskperchild表示每个工作进程在退出/被其他新的进程替代前,需要完成的工作任务数,默认为None,表示工作进程存活时间与pool相同,即不会自动退出/被替换。
函数返回一个进程池(Pool)对象

  Pool函数返回的进程池对象中有下面一些数据结构:

self._inqueue  接收任务队列(SimpleQueue),用于主进程将任务发送给worker进程
self._outqueue 发送结果队列(SimpleQueue),用于worker进程将结果发送给主进程
self._taskqueue 同步的任务队列,保存线程池分配给主进程的任务
self._cache = {} 任务缓存
self._processes worker进程个数
self._pool = [] woker进程队列

  进程池工作时,任务的接收、分配。结果的返回,均由进程池内部的各个线程合作完成,来看看进程池内部由那些线程:

  • _work_handler线程,负责保证进程池中的worker进程在有退出的情况下,创建出新的worker进程,并添加到进程队列(pools)中,保持进程池中的worker进程数始终为processes个。_worker_handler线程回调函数为Pool._handler_workers方法,在进程池state==RUN时,循环调用_maintain_pool方法,监控是否有进程退出,并创建新的进程,append到进程池pools中,保持进程池中的worker进程数始终为processes个。

    self._worker_handler = threading.Thread(
    target=Pool._handle_workers,
    args=(self, )
    )
    Pool._handle_workers方法在_worker_handler线程状态为运行时(status==RUN),循环调用_maintain_pool方法:
    def _maintain_pool(self):
    if self._join_exited_workers():
    self._repopulate_pool()
    _join_exited_workers()监控pools队列中的进程是否有结束的,有则等待其结束,并从pools中删除,当有进程结束时,调用_repopulate_pool(),创建新的进程:
    w = self.Process(target=worker,
       args=(self._inqueue, self._outqueue,
      self._initializer, self._initargs,           
    self._maxtasksperchild)
    )
    self._pool.append(w)
    w是新创建的进程,它是用来处理实际任务的进程,worker是它的回调函数:
    def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None):
    assert maxtasks is None or (type(maxtasks) == int and maxtasks > 0)
    put = outqueue.put
    get = inqueue.get
    if hasattr(inqueue, '_writer'):
    inqueue._writer.close()
    outqueue._reader.close() if initializer is not None:
    initializer(*initargs) completed = 0
    while maxtasks is None or (maxtasks and completed < maxtasks):
    try:
    task = get()
    except (EOFError, IOError):
    debug('worker got EOFError or IOError -- exiting')
    break if task is None:
    debug('worker got sentinel -- exiting')
    break job, i, func, args, kwds = task
    try:
    result = (True, func(*args, **kwds))
    except Exception, e:
    result = (False, e)
    try:
    put((job, i, result))
    except Exception as e:
    wrapped = MaybeEncodingError(e, result[1])
    debug("Possible encoding error while sending result: %s" % (
    wrapped))
    put((job, i, (False, wrapped)))
    completed += 1
    debug('worker exiting after %d tasks' % completed) 所有worker进程都使用worker回调函数对任务进行统一的处理,从源码中可以看出:
    它的功能是从接入任务队列中(inqueue)读取出task任务,然后根据任务的函数、参数进行调用(result = (True, func(*args, **kwds),
    再将结果放入结果队列中(outqueue),如果有最大处理上限的限制maxtasks,那么当进程处理到任务数上限时退出。
  • _task_handler线程,负责从进程池中的task_queue中,将任务取出,放入接收任务队列(Pipe),
    self._task_handler = threading.Thread(
    target=Pool._handle_tasks,
    args=(self._taskqueue, self._quick_put, self._outqueue, self._pool)
    )
    Pool._handle_tasks方法不断从task_queue中获取任务,并放入接受任务队列(in_queue),以此触发worker进程进行任务处理。当从task_queue读取到None元素时,
    表示进程池将要被终止(terminate),不再处理之后的任务请求,同时向接受任务队列和结果任务队列put None元素,通知其他线程结束。
  • _handle_results线程,负责将处理完的任务结果,从outqueue(Pipe)中读取出来,放在任务缓存cache中,
    self._result_handler = threading.Thread(
            target=Pool._handle_results,
            args=(self._outqueue, self._quick_get, self._cache)
    )
  • _terminate,这里的_terminate并不是一个线程,而是一个Finalize对象
    self._terminate = Finalize(
    self, self._terminate_pool,
    args=(self._taskqueue, self._inqueue, self._outqueue, self._pool,
    self._worker_handler, self._task_handler,
    self._result_handler, self._cache),
    exitpriority=15
    )
    Finalize类的构造函数与线程构造函数类似,_terminate_pool是它的回调函数,args回调函数的参数。
    _terminate_pool函数负责终止进程池的工作:终止上述的三个线程,终止进程池中的worker进程,清除队列中的数据。
    _terminate是个对象而非线程,那么它如何像线程调用start()方法一样,来执行回调函数_terminate_pool呢?查看Pool源码,发现进程池的终止函数:
    def terminate(self):
        debug('terminating pool')
        self._state = TERMINATE
        self._worker_handler._state = TERMINATE
        self._terminate()
    函数中最后将_terminate对象当做一个方法来执行,而_terminate本身是一个Finalize对象,我们看一下Finalize类的定义,发现它实现了__call__方法:
    def __call__(self, wr=None):
        try:
            del _finalizer_registry[self._key]
        except KeyError:
            sub_debug('finalizer no longer registered')
        else:
            if self._pid != os.getpid():
                res = None
            else:
                res = self._callback(*self._args, **self._kwargs)
            self._weakref = self._callback = self._args = \
                            self._kwargs = self._key = None
            return res
    而方法中 self._callback(*self._args, **self._kwargs) 这条语句,就执行了_terminate_pool函数,进而将进程池终止。

  进程池中的数据结构、各个线程之间的合作关系如下图所示:

aaarticlea/png;base64,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" alt="" />

  【1】这里针对的是CPU密集型程序,多线程并不能带来效率上的提升,相反还可能会因为线程的频繁切换,导致效率下降;如果是IO密集型,多线程进程可以利用IO阻塞等待时的空闲时间执行其他线程,提升效率。

  未完待续……

python进程池剖析(一)的更多相关文章

  1. python进程池剖析(三)

    之前文章对python中进程池的原理.数据流以及应用从代码角度做了简单的剖析,现在让我们回头看看标准库中对进程池的实现都有哪些值得我们学习的地方.我们知道,进程池内部由多个线程互相协作,向客户端提供可 ...

  2. python进程池剖析(二)

    之前文章中介绍了python中multiprocessing模块中自带的进程池Pool,并对进程池中的数据结构和各个线程之间的合作关系进行了简单分析,这节来看下客户端如何对向进程池分配任务,并获取结果 ...

  3. python进程池:multiprocessing.pool

    本文转至http://www.cnblogs.com/kaituorensheng/p/4465768.html,在其基础上进行了一些小小改动. 在利用Python进行系统管理的时候,特别是同时操作多 ...

  4. python(进程池/线程池)

    进程池 import multiprocessing import time def do_calculation(data): print(multiprocessing.current_proce ...

  5. 万里长征第一步:Python进程池的一点点小坑

    # -*- coding: utf- -*- """ Created on Thu Mar :: @author: lilide """ # ...

  6. python进程池

    当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiproce ...

  7. python 进程池的简单使用方法

    回到python,用一下python的进程池. 记得之前面试的时候,面试官问:你知道进程池的默认参数吗? 我没有回答上来,后来才知道,是有默认参数的.下面就看看它的默认参数 1. 不加参数 from ...

  8. python 进程池pool简单使用

    平常会经常用到多进程,可以用进程池pool来进行自动控制进程,下面介绍一下pool的简单使用. 需要主动是,在Windows上要想使用进程模块,就必须把有关进程的代码写if __name__ == ‘ ...

  9. python 进程池Pool以及Queue的用法

    import os,time,random from multiprocessing import Pool def task(name): print('正在运行的任务:%s,PID:(%s)'%( ...

随机推荐

  1. 初识 Cloudera Impala

    Impala是Cloudera公司主导开发的新型查询系统,它提供SQL语义,能查询存储在Hadoop的HDFS和HBase中的PB级大数据.已有的Hive系统尽管也提供了SQL语义,但因为Hive底层 ...

  2. XeTeX中文解决方案(temp)

    临时记录一下XeTeX的中文解决方案.一些包的文档只是走马观花得到的解决方法,所以可能有诸多纰漏. 另个人还是比较看好LuaTeX,但是在里边鼓捣中文还是一团糟,等探索一下再回来补充. 我使用的包是x ...

  3. JAVA web四个属性的范围汇总

    首先,你需要知道client跳跃和server差别: client跳转: response.sendRedict(String path),地址栏发生改变. 不能传递request属性. server ...

  4. Oracle 多行转多列

    Oracle 多行转多列,列值转为列名   前段时间做调查问卷,客户创建自定义问卷内容,包括题目和选项内容; 之后需要到处问卷明细,,,,麻烦来咯 于是到网上到处搜索,没有直接结果;于是又找各种相似的 ...

  5. Is it always safe to call getClass() within the subclass constructor?(转)

    14down votefavorite   An article on classloading states that the method getClass() should not be cal ...

  6. 安装 CentOS 7 后必做的七件事

    原文 安装 CentOS 7 后必做的七件事 CentOS 是最多人用来运行服务器的 Linux 版本,最新版本是 CentOS 7.当你兴趣勃勃地在一台主机或 VPS 上安装 CentOS 7 后, ...

  7. BMP图片转换为JPEG图片

    原文:BMP图片转换为JPEG图片 昨天在家学习,发现很多人把BMP图片转换为其它图片格式,有些人写得简单,有些人写得复杂. Insus.NET在想,一直在做文件上传,下载,或是图片剪切,都有进行过文 ...

  8. springMVC3得知(五岁以下儿童)--MultiActionController

    Spring为了提供一个多动作控制器,您可以使用它的几个行动统一到一个控制器,这可以放在一起功能. 多动作控制器存在在一个单独的包中--org.springframework.web.mvc.mult ...

  9. .NET缓存框架CacheManager---1、CacheManager的介绍

    在我们开发的很多分布式项目里面(如基于WCF服务.Web API服务方式),由于数据提供涉及到数据库的相关操作,如果客户端的并发数量超过一定的数量,那么数据库的请求处理则以爆发式增长,如果数据库服务器 ...

  10. Python的print中国输出对齐问题

    问题叙述性说明: 在使用Python内置函数print当输出英语,应用格输出类型可以对齐很好: s1 = 'I am a long sentence.' s2 = 'I\'m short.' prin ...