python学习笔记——multiprocess 多进程组件Pool

1 进程池Pool基本概述

在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量时间,如果操作的对象数目不大时,还可以直接适用Process类动态生成多个进程,几十个尚可,若上百个甚至更多时,手动限制进程数量就显得特别繁琐,此时进程池就显得尤为重要。

进程池Pool类可以提供指定数量的进程供用户调用,当有新的请求提交至Pool中时,若进程池尚未满,就会创建一个新的进程来执行请求;若进程池中的进程数已经达到规定的最大数量,则该请求就会等待,直到进程池中有进程结束,才会创建新的进程来处理该请求。

2 进程池Pool的语法

Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])

processes:使用的工作进程的数量;若processes是None,默认适用os.cpu_count()返回的数量。

initializer:若initializer是None,则每一个工作进程在开始的时候就会调用initializer(*initargs)。

maxtasksperchild:工作进程退出前可以完成的任务数,完成后用一个新的工作进程来替代原进程,让闲置的资源释放,maxtasksperchild默认是None,此意味只要Pool存在工作进程就一直存活

context: 用在制定工作进程启动时的上下文,一般使用multiprocessing.Pool()或者一个context对象的Pool()方法来创建一个池,两种方法都适当的设置了context。

实例方法:

p为进程池对象

p.apply():

 apply(func[, args=()[, kwds={}]]) 

该函数用于传递不定参数,主进程会被阻塞直到函数执行结束,实际上这也就说所谓的同步执行。

同步执行,按照加入进程池的顺序执行事件,每次执行完一个再执行另一个,无法获取返回值

p.apply_async()

apply_async(func[, args=()[, kwds={}[, callback=None]]])

与apply用法一样,但它是非阻塞且支持结果返回进行回调;实际上也就是异步执行。

异步执行,同时启动进程池中多个进程执行事件,可以获取事件返回值 — <multiprocessing.pool.ApplyResult object at 0x7f7f6e4357f0>

p.map()

map(func, iterable[, chunksize=None])

Pool类中的map方法,与内置map函数用法基本一致,它融合了map函数和apply_async()函数的功能;它会使进程阻塞直到返回结果。

注意:虽然第二个参数是一个迭代器,但实际应用中,必须在整个队列就绪后,程序才会运行子进程。

p.close():关闭进程池,阻止更多的任务提交到进程池Pool,待任务完成后,工作进程会退出

p.terminate():结束工作进程,不再处理未完成的任务

p.join():等待工作线程的退出,必须在close()或terminate()之后使用,因被终止的进程需要被父进程调用wait(join等价于wait),否则进程会成为僵尸进程。

注意:

(1)使用Pool创建进程池对象,同时进程池中进程已经启动

(2)向进程池对象中添加事件,事件排队执行

(3)如果主进程退出,则进程池中所有进程都退出

3 实例

3.1 基础实例

import multiprocessing as mp

def test():
    pass

p = mp.Pool(processes = 5) # 创建5条进程

for i in range(10):
    p.apply_async(test) # 向进程池添加任务

p.close() # 关闭进程池,不再接受请求
p.join() # 等待所有的子进程结束

说明:

(1)进程池Pool被创建出来后, p.apply_async(test) 语句不停地循环执行,相当于向进程池中提交了10个请求,它们会被放到一个队列中。

(2) p = mp.Pool(5) 执行完毕后创建了5条进程,但尚未给它们分配各自的任务;也就意味着,无论有多少任务,实际的进程数只有5条,每次最多5条进程并行。

(3)当Pool中有进程任务执行完毕后,这条进程资源会被释放,Pool会按先进先出的原则取出一个新的请求给空闲的进程继续执行。

(4)当Pool所有的进程任务完成后,会产生5个僵尸进程,如果主进程/主线程不结束,系统不会自动回收资源,需要调用join函数负责回收。

(5)在创建Pool进程池时,若不指定进程的最大数量,默认创建的进程数为系统的内核数量

(6)如果采用p.apply(test)阻塞方式添加任务,其每次只能向进程池中添加一条任务,然后for循环会被阻塞等待,直到添加的任务被执行完毕,进程池中的5个进程交替执行新来的任务,此时相当于单进程。——该语句需要再深刻理解,尚未完全明白

参考:python的multiprocessing模块进程创建、资源回收-Process,Pool

3.2 apply方式添加任务

import  multiprocessing as mp
import os
from time import sleep

def worker(msg):
    print(os.getpid())
    sleep(2)
    print(msg)
    return msg

#创建进程池对象
p = mp.Pool(processes = 4)#创建4条进程

pool_result = []
for i in range(10):
    msg = ‘hello-%d‘%i
    r = p.apply(worker,(msg,))#向进程池中添加事件
    pool_result.append(r)

#获取事件函数的返回值
for r in pool_result:
    print(‘return:‘,r) 

p.close()# 关闭进程池,不再接受请求
p.join() # 等待进程池中的事件执行完毕,回收进程池

运行

8419
hello-0
8418
hello-1
8420
hello-2
8421
hello-3
8419
hello-4
8418
hello-5
8420
hello-6
8421
hello-7
8419
hello-8
8418
hello-9
return: hello-0
return: hello-1
return: hello-2
return: hello-3
return: hello-4
return: hello-5
return: hello-6
return: hello-7
return: hello-8
return: hello-9

这段代码运行较慢,和进程阻塞有关。相当于单线程!

当将代码(22行)中的 print(‘return:‘,r)  修改为 print(‘return:‘,r.get())  时

8670
hello-0
8671
hello-1
8672
hello-2
8673
hello-3
8670
hello-4
8671
hello-5
8672
hello-6
8673
hello-7
8670
hello-8
8671
hello-9
Traceback (most recent call last):
  File "test1.py", line 22, in <module>
    print(‘return:‘,r.get())
AttributeError: ‘str‘ object has no attribute ‘get‘

最后报错: AttributeError: ‘str‘ object has no attribute ‘get‘

3.3 applay_async方式添加任务

import multiprocessing as mp
import os
from time import sleep 

def worker(msg):
    print(os.getpid())
    sleep(2)
    print(msg)
    return msg

#创建进程池对象
p = mp.Pool(processes = 4) #创建4条进程

pool_result = []
for i in range(10):
    msg = ‘hello-%d‘%i
    r = p.apply_async(worker,(msg,)) #向进程池中添加事件
    pool_result.append(r)

#获取事件函数的返回值
for r in pool_result:
    print(‘return:‘,r)

p.close()#关闭进程池,不再接受请求
p.join()# 等待进程池中的事件执行完毕,回收进程池

运行

return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37d68>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37e80>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37f98>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e410f0>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41208>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41320>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41438>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41550>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41668>
return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41780>
8739
8740
8742
8741
hello-0
hello-3
8742
hello-1
8739
8740
hello-2
8741
hello-5
8739
hello-6
8740
hello-7
hello-4
hello-8
hello-9

注意:

(1)由于这个是异步方式添加任务,所以运行非常快

(2)由于for是内置循环函数,执行效率较高,所以在结果的前10行均为for语句执行结果

(3) r = p.apply_async(worker,(msg,)) 执行结果为进度对象。

(4)由于任务是异步执行,所以在结果中是“乱序”;并不像applay那样有序打印。

同样将代码(22行)中的 print(‘return:‘,r) 修改为 print(‘return:‘,r.get())  时,

运行结果

8839
8840
8841
8842
hello-0
hello-1
hello-3
8839
hello-2
8842
8841
8840
return: hello-0
return: hello-1
return: hello-2
return: hello-3
hello-4
hello-5
8839
hello-6
8842
hello-7
return: hello-4
return: hello-5
return: hello-6
return: hello-7
hello-9
hello-8
return: hello-8
return: hello-9

原文地址:https://www.cnblogs.com/gengyi/p/8620853.html

时间: 2024-10-28 00:42:42

python学习笔记——multiprocess 多进程组件Pool的相关文章

python学习笔记(多进程并发)

理论篇: 1.什么是进程: 进程:计算机系统中正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 2.进程和程序的区别: 程序是实现功能的一堆代码,而进程是程序运行的过程. 注:同一个程序同时打开两次或多次,就会启动两个或多个进程. 3.并发与并行: 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务 一 并发:是伪并行,即看起来是同时运行.单个cpu+多道技术就可以实现

Python学习笔记进阶篇——总览

Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(Socket编程进阶&多线程.多进程) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(异常处理) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(多线程与进程池) Python学习笔记——进阶篇[第九周]———线程.进程.协程篇(队列Queue和生产者消费者模型) Python学习笔记——进阶篇[第九周]———协程 Python学习笔记——进阶篇[第九周]———MYSQL操作

python &nbsp; 学习笔记 (核心)

python    学习笔记 (核心) Python解释器从头到尾一行接一行执行脚本 # -*- coding: UTF-8 -*-    //字符编码 不区分单引号和双引号,x='hello',x[0],x[-1]指最后一个字符,x[2:4]取子串, '''hello''' #hello三引号会保留文本输入时的换行符制表符等不需要转义,用于多行原样输入保存 'hello'+'world' #字符串拼接,'hello'*2 #字符串重复 help(fun) #帮助,help(module.met

Tornado/Python 学习笔记(二)

部分ssrpc.py代码分析 -- 服务端: 1 #!/usr/bin/python3 2 3 from xmlrpc.client import Fault, dumps, loads 4 import sys 5 from socketserver import ForkingMixIn 6 from xmlrpc.server import SimpleXMLRPCServer 7 8 class VerboseFaultXMLRPCServer(SimpleXMLRPCServer):

OpenCV之Python学习笔记

OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书<OpenCV Computer Vision with Python>,于是就看一遍,顺便把自己掌握的东西整合一下,写成学习笔记了.更需要的朋友参考. 阅读须知: 本文不是纯粹的译文,只是比较贴近原文的笔记:         请设法购买到出版社出版的书,支持正版. 从书名就能看出来本书是介绍在Pytho

Vue学习笔记入门篇——组件的使用

本文为转载,原文:Vue学习笔记入门篇--组件的使用 组件定义 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展. 组件使用 注册 注册一个全局组件,你可以使用 Vue.component(tagName, options).组件在注册之后,便可以在父实例的模块中以自定义元素 的形式使用.

Vue学习笔记入门篇——组件的内容分发(slot)

本文为转载,原文:Vue学习笔记入门篇--组件的内容分发(slot) 介绍 为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板.这个过程被称为 内容分发 (或 "transclusion" 如果你熟悉 Angular).Vue.js 实现了一个内容分发 API,使用特殊的 'slot' 元素作为原始内容的插槽. 编译作用域 在深入内容分发 API 之前,我们先明确内容在哪个作用域里编译.假定模板为: <child-component> {{ messa

python学习笔记12-模块使用

python学习笔记12-模块使用 模块os,sys 什么是模块? 模块os,sys 模块是Python组织代码的一种基本方式 一个Python脚本可以单独运行,也可以导入到另外一个脚本运行,用import hello语句来导入,不用加入.py 什么是Python的 包? Python的模块可以按照目录组织为包 创建一个包的步骤: 创建一个名字为包名的目录 在改目录下创建一个__init__.py文件 根据需要,在该目录下存放脚本文件或已编译的扩展及子包 import pack.m1,pack.

python学习笔记2—python文件类型、变量、数值、字符串、元组、列表、字典

python学习笔记2--python文件类型.变量.数值.字符串.元组.列表.字典 一.Python文件类型 1.源代码 python源代码文件以.py为扩展名,由pyton程序解释,不需要编译 [[email protected] day01]# vim 1.py #!/usr/bin/python        print 'hello world!' [[email protected] day01]# python 1.py hello world! 2.字节代码 Python源码文件