python多进程那点事儿【multiprocessing库】
前言:项目中有个需求需要对产品的日志处理,按照产品中日志的某些字段,对日志进行再次划分。比如产品的日志中含有字段id,tag=1,现在需要把tag是基数的放到一个文件中,tag是偶数的放入一个文件中。这就涉及到多个文件的读写操作,一个文件一个文件读取写入那时间太久了,公司配备的单机,跑了半个多小时,光标还是一直在闪闪闪【你懂得】。没办法了,还是用多进程跑吧。这就得对python中的多进程从新回顾一遍了。
Q1:为什么不用多线程呢?
A1:这个就需要了解python多线程的实现原理了,通过在其解释器层面施加一个全局锁来保证同一时刻只有一个线程可以拥有锁,执行相应的python字节码。所以虽然冠名是是多线程,但是实质上还是只有一个线程在运行。有时候多线程可能会让程序得不到提高反而降低,因为线程之间需要竞争资源。所以很多人也说,如果想真正的同一时刻执行多个任务的话,就需要使用多进程。
1.使用multiprocessing.Process
multiprocessing.Process最常见的使用就是:
p = multiprocessing.Process(target = 多线程执行函数名, args = 函数参数元组形式)
p.start()
p.join()
注意使用多进程时候一定要使用join对子进程的状态进行收集,否则在程序运行过程中会出现僵尸进程,对系统性能造成影响。
当然,上面这只有一个进程,你在写的时候可能很顺手就写了
for x in range(10):
p = multiprocessing.Process(target = 多线程执行函数名, args = 函数参数元组形式)
p.start()
p.join()
然后就发现,这个进程貌似是顺序执行的。。。好像没有并发,原因就出现在join的位置上,仔细查看手册,你会发现在join函数下方有一行说明:
Block the calling thread until the process whose join() method is called terminates or until the optional timeout occurs.
意思就是主线程会在join的地方一直等子进程结束。。那么我们多个进程并发执行就要这样写了:
p_list = []
for x in range(10):
p = multiprocessing.Process(target = 多线程执行函数名, args = 函数参数元组形式)
p.start()
p_list.append(p) for p in p_list:
p.join()
感觉这样写的代码一点都不优雅,而且以后拓展也很不方便,子进程的数目会随着任务数目的增加而增加,进程得不到重复的利用。
2.使用multiprocessing.Pool
进程池就是上述不方便的完美解决,其一般用法如下:
pool = multiprocessing.Pool(processes=进程数目)
for x in xrange(任务数目):
pool.apply_async(函数名, 函数参数元组形式)
pool.close() # close函数表明不会再往进程池中加入新任务,一定要在join方法调用之前调用。
pool.join()
上述代码开启了含有一定数目的进程池,只需要往进程池中加入新任务即可,当进程池中已满,其他的任务就等待,直到有任务结束。
注意:除了pool.apply_async方法,还有一个pool.apply方法,只不过pool.apply方法是阻塞的。
还可以使用进程池方法来关注进程执行的结果,pool.apply_asyn函数即返回函数的执行结果,使用get()方法即可得到。
3.多进程共享数据
多个进程之间共享数据也有很多种方法:
1)共享变量
只能使用Value和Array方法:
multiprocessing.Value(typecode_or_type, *args[, lock])
multiprocessing.Array(typecode_or_type, size_or_initializer, *, lock=True)
关于lock的一段说明:
Return a process-safe wrapper object for a ctypes object which uses lock to synchronize access. If lock is None (the default) then a multiprocessing.RLock object is created automatically.
共享变量只能是一个变量,或者是线性的一组变量,类型也是从typecode_or_type衍生而来的,具体的用法和说明手册上已经讲解的很清楚了。附上手册上的一段代码如下:
from multiprocessing import Process, Lock
from multiprocessing.sharedctypes import Value, Array
from ctypes import Structure, c_double class Point(Structure):
_fields_ = [('x', c_double), ('y', c_double)] def modify(n, x, s, A):
n.value **= 2
x.value **= 2
s.value = s.value.upper()
for a in A:
a.x **= 2
a.y **= 2 if __name__ == '__main__':
lock = Lock() n = Value('i', 7)
x = Value(c_double, 1.0/3.0, lock=False)
s = Array('c', 'hello world', lock=lock)
A = Array(Point, [(1.875,-6.25), (-5.75,2.0), (2.375,9.5)], lock=lock) p = Process(target=modify, args=(n, x, s, A))
p.start()
p.join() print n.value
print x.value
print s.value
print [(a.x, a.y) for a in A]
结果:
49
0.1111111111111111
HELLO WORLD
[(3.515625, 39.0625), (33.0625, 4.0), (5.640625, 90.25)]
2)Manager
使用Manager方法时,共享变量的类型会多一些,例如list,dict,Event,Lock,Array,Value...使用Manager方法时需要注意,在操作共享对象时候,除了赋值操作,其他的方法都作用在共享对象的拷贝上,并不会对共享对象生效。例如:
d = Manager().dict()
d[0] = []
d[0].append(0) # append方法作用在代理对象上,并不对原始对象生效
print d
输出:{0: []}
而同样意思的一段代码:
d = Manager().dict()
l = []
l.append(0)
d[0] = l # 直接赋值操作,影响原始共享对象
print d
输出:{0: [0]}
3)Queue
队列,顾名思义,就是一组数据,使用put来往队列中存入数据,使用get方法获取数据,当队列满了继续put和队列空了继续get时候会抛出相对应的异常。可以多个进程之间传递数据。
4)Pipe
Pipe方法返回(conn1, conn2)代表一个管道的两个端,对应两个进程。还可以通过duplex来设定管道是全双工(duplex=True)还是半双工(duplex=False)工作。send和recv方法分别是发送和接受消息的方法,如果没有消息可接收,recv方法会一直阻塞。如果管道已经被关闭,那么recv方法会抛出EOFError。
4.多进程同步互斥
1)Lock和Semaphore
这两个就不多讲了,学过操作系统的都知道。Lock限定同一时间仅一个进程访问共享变量,Semaphore则可以限定多个进程同时访问共享变量。
2)Event
使用set和is_set判断事件是否已经发生,决定下一步要执行的动作。
python多进程那点事儿【multiprocessing库】的更多相关文章
- Python: 多进程的分布式进程multiprocessing.managers
multiprocessing.managers 在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分 ...
- Python 多进程异常处理
前言 最近项目用到了Python作为网站的前端,使用的框架是基于线程池的Cherrypy,但是前端依然有一些比较‘重’的模块.由于python的多线程无法很好的利用多核的性质,所以觉得把这些比较‘重’ ...
- Python多进程库multiprocessing中进程池Pool类的使用[转]
from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...
- Python多进程库multiprocessing创建进程以及进程池Pool类的使用
问题起因最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果.没错!类似bag ...
- Python多进程multiprocessing使用示例
mutilprocess简介 像线程一样管理进程,这个是mutilprocess的核心,他与threading很是相像,对多核CPU的利用率会比threading好的多. import multipr ...
- Python多进程并发(multiprocessing)用法实例详解
http://www.jb51.net/article/67116.htm 本文实例讲述了Python多进程并发(multiprocessing)用法.分享给大家供大家参考.具体分析如下: 由于Pyt ...
- Python 多进程multiprocessing
一.python多线程其实在底层来说只是单线程,因此python多线程也称为假线程,之所以用多线程的意义是因为线程不停的切换这样比串行还是要快很多.python多线程中只要涉及到io或者sleep就会 ...
- Python多进程池 multiprocessing Pool
1. 背景 由于需要写python程序, 定时.大量发送htttp请求,并对结果进行处理. 参考其他代码有进程池,记录一下. 2. 多进程 vs 多线程 c++程序中,单个模块通常是单进程,会启动几十 ...
- python多进程-----multiprocessing包
multiprocessing并非是python的一个模块,而是python中多进程管理的一个包,在学习的时候可以与threading这个模块作类比,正如我们在上一篇转载的文章中所提,python的多 ...
随机推荐
- python自动化运维笔记3 —— dns处理模块dnspython
1.3 DNS处理模块 dnspython是python实现的一个DNS工具包,它支持几乎所有的记录类型,可以用于查询.传输并动态更新ZONE信息,同时支持TSIG(事物签名)验证消息和EDNS0(扩 ...
- BZOJ5311 贞鱼(动态规划+wqs二分+决策单调性)
大胆猜想答案随k变化是凸函数,且有决策单调性即可.去粘了份fread快读板子才过. #include<iostream> #include<cstdio> #include&l ...
- 使用正则真正的修改TP5的config.php文件
来源 https://www.kancloud.cn/manual/thinkphp5/118026 问题 前台传值后台使用Config::set()方法写入config.php文件,但是并没有真正的 ...
- POJ1905-Expanding Rods-二分答案
一根细棒升温时会变长,在两面墙中间,会变成一个弓形. 给出变长后的长度,求新的细棒中心与没伸长时的中心的距离. 简单的数学推导后就可以二分答案了,一开始没完全掌握二分的姿势,wa了好多.而且poj d ...
- ROADS POJ - 1724(分层最短路)
就是在最短路的基础上 多加了一个时间的限制 , 多一个限制多一维就好了 记住 分层最短路要用dijistra !!! #include <iostream> #include < ...
- hdu 3911 Black And White (线段树 区间合并)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911 题意: 给你一段01序列,有两个操作: 1.区间异或,2.询问区间最长的连续的1得长度 思路: ...
- MT【58】反演圆和极线极点和谐统一
解答:如图 评:1.反演圆及其性质介绍: 评2:此题的源头是1995年全国卷压轴题,这里用极线极点的相关性质也可以处理: 注:用相关点法很容易得到轨迹.
- copy elison & RVO & NRVO
蓝色的博文 To summarize, RVO is a compiler optimization technique, while std::move is just an rvalue cast ...
- BZOJ 4806 - 4809 象棋四题
4806: 炮 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 103 Solved: 72[Submit][Status][Discuss] Des ...
- BZOJ 3526: [Poi2014]Card
3526: [Poi2014]Card Time Limit: 25 Sec Memory Limit: 64 MBSubmit: 267 Solved: 191[Submit][Status][ ...