python多进程控制学习小结
作者:青云 发布时间:2021-08-31 00:48:57
前言:
python多进程,经常在使用,却没有怎么系统的学习过,官网上面讲得比较细,结合自己的学习,整理记录下官网:https://docs.python.org/3/library/multiprocessing.html
multiprocessing简介
multiprocessing是python自带的多进程模块,可以大批量的生成进程,在服务器为多核CPU时效果更好,类似于threading模块。相对于多线程,多进程由于独享内存空间,更稳定安全,在运维里面做些批量操作时,多进程有更多适用的场景
multiprocessing包提供了本地和远程两种并发操作,有效的避开了使用子进程而不是全局解释锁的线程,因此,multiprocessing可以有效利用到多核处理
Process类
在multiporcessing中,通过Process类对象来批量产生进程,使用start()方法来启动这个进程
1.语法
multiprocessing.Process(group=None,target=None,name=None,args=(),kwargs={},*)
group: 这个参数一般为空,它只是为了兼容threading.Tread
target: 这个参数就是通过run()可调用对象的方法,默认为空,表示没有方法被调用
name: 表示进程名
args: 传给target调用方法的tuple(元组)参数
kwargs: 传给target调用方法的dict(字典)参数
2.Process类的方法及对象
run()
该方法是进程的运行过程,可以在子类中重写此方法,一般也很少去重构
start()
启动进程,每个进程对象都必须被该方法调用
join([timeout])
等待进程终止,再往下执行,可以设置超时时间
name
可以获取进程名字,多个进程也可以是相同的名字
is_alive()
返回进程是否还存活,True or False,进程存活是指start()开始到子进程终止
daemon
守护进程的标记,一个布尔值,在start()之后设置该值,表示是否后台运行
注意:如果设置了后台运行,那么后台程序不运行再创建子进程
pid
可以获取进程ID
exitcode
子进程退出时的值,如果进程还没有终止,值将是None,如果是负值,表示子进程被终止
terminate()
终止进程,如果是Windows,则使用terminateprocess(),该方法对已经退出和结束的进程,将不会执行
以下为一个简单的例子:
#-*- coding:utf8 -*-
import multiprocessing
import time
def work(x):
time.sleep(1)
print time.ctime(),'这是子进程[{0}]...'.format(x)
if __name__ == '__main__':
for i in range(5):
p = multiprocessing.Process(target=work,args=(i,))
print '启动进程数:{0}'.format(i)
p.start()
p.deamon = True
当然也可以显示每个进程的ID
#-*- coding:utf8 -*-
import multiprocessing
import time
import os
def work(x):
time.sleep(1)
ppid = os.getppid()
pid = os.getpid()
print time.ctime(),'这是子进程[{0},父进程:{1},子进程:{2}]...'.format(x,ppid,pid)
if __name__ == '__main__':
for i in range(5):
p = multiprocessing.Process(target=work,args=(i,))
print '启动进程数:{0}'.format(i)
p.start()
p.deamon = True
但在实际使用的过程中,并不只是并发完就可以了,比如,有30个任务,由于服务器资源有限,每次并发5个任务,这里还涉及到30个任务怎么获取的问题,另外并发的进程任务执行时间很难保证一致,尤其是需要时间的任务,可能并发5个任务,有3个已经执行完了,2个还需要很长时间执行,总不能等到这两个进程执行完了,再继续执行后面的任务,因此进程控制就在此有了使用场景,可以利用Process的方法和一些multiprocessing的包,类等结合使用
进程控制及通信常用类
一、Queue类
类似于python自带的Queue.Queue,主要用在比较小的队列上面
语法:
multiprocessing.Queue([maxsize])
类方法:
qsize()
返回队列的大致大小,因为多进程或者多线程一直在消耗队列,因此该数据不一定正确
empty()
判断队列是否为空,如果是,则返回True,否则False
full()
判断队列是否已满,如果是,则返回True,否则False
put(obj[, block[, timeout]])
将对象放入队列,可选参数block为True,timeout为None
get()
从队列取出对象
#-*- coding:utf8 -*-
from multiprocessing import Process, Queue
def f(q):
q.put([42,None,'hi'])
if __name__ == '__main__':
q = Queue()
p = Process(target=f, args=(q,))
p.start()
print q.get() #打印内容: [42,None,'hi']
p.join()
二、Pipe类
pipe()函数返回一对对象的连接,可以为进程间传输消息,在打印一些日志、进程控制上面有一些用处,Pip()对象返回两个对象connection,代表两个通道,每个connection对象都有send()和recv()方法,需要注意的是两个或以上的进程同时读取或者写入同一管道,可能会导致数据混乱,测试了下,是直接覆盖了。另外,返回的两个connection,如果一个是send()数据,那么另外一个就只能recv()接收数据了
#-*- coding:utf8 -*-
from multiprocessing import Process, Pipe
import time
def f(conn,i):
print '[{0}]已经执行到子进程:{1}'.format(time.ctime(),i)
time.sleep(1)
w = "[{0}]hi,this is :{1}".format(time.ctime(),i)
conn.send(w)
conn.close()
if __name__ == '__main__':
reader = []
parent_conn, child_conn = Pipe()
for i in range(4):
p = Process(target=f, args=(child_conn,i))
p.start()
reader.append(parent_conn)
p.deamon=True
# 等待所有子进程跑完
time.sleep(3)
print '\n[{0}]下面打印child_conn向parent_conn传输的信息:'.format(time.ctime())
for i in reader:
print i.recv()
输出为:
三、Value,Array
在进行并发编程时,应尽量避免使用共享状态,因为多进程同时修改数据会导致数据破坏。但如果确实需要在多进程间共享数据,multiprocessing也提供了方法Value、Array
from multiprocessing import Process, Value, Array
def f(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] = -a[i]
if __name__ == '__main__':
num = Value('d',0.0)
arr = Array('i', range(10))
p = Process(target=f, args=(num, arr))
p.start()
p.join()
print num.value
print arr[:]
3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]*
四、Manager进程管理模块
Manager类管理进程使用得较多,它返回对象可以操控子进程,并且支持很多类型的操作,如: list, dict, Namespace、lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value, Array,因此使用Manager基本上就够了
from multiprocessing import Process, Manager
def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.reverse()
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list(range(10))
p = Process(target=f, args=(d, l))
p.start()
p.join() #等待进程结束后往下执行
print d,'\n',l
输出:
{0.25: None, 1: '1', '2': 2}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
可以看到,跟共享数据一样的效果,大部分管理进程的方法都集成到了Manager()模块了
五、对多进程控制的应用实例
#-*- coding:utf8 -*-
from multiprocessing import Process, Queue
import time
def work(pname,q):
time.sleep(1)
print_some = "{0}|this is process: {1}".format(time.ctime(),pname)
print print_some
q.put(pname)
if __name__ == '__main__':
p_manag_num = 2 # 进程并发控制数量2
# 并发的进程名
q_process = ['process_1','process_2','process_3','process_4','process_5']
q_a = Queue() # 将进程名放入队列
q_b = Queue() # 将q_a的进程名放往q_b进程,由子进程完成
for i in q_process:
q_a.put(i)
p_list = [] # 完成的进程队列
while not q_a.empty():
if len(p_list) <= 2:
pname=q_a.get()
p = Process(target=work, args=(pname,q_b))
p.start()
p_list.append(p)
print pname
for p in p_list:
if not p.is_alive():
p_list.remove(p)
# 等待5秒,预估执行完后看队列通信信息
# 当然也可以循环判断队列里面的进程是否执行完成
time.sleep(5)
print '打印p_b队列:'
while not q_b.empty():
print q_b.get()
执行结果:
来源:https://segmentfault.com/a/1190000016855803
猜你喜欢
- 本文实例讲述了Django利用cookie保存用户登录信息的方法。分享给大家供大家参考,具体如下:设置cookieresponse对象.se
- 前言:如今,大多数计算机都带有多个内核,允许多个线程并行运行计算。即使处理器只有单核,也可以通过并发编程来提升程序的运行效率,比如在一个线程
- 紧接上篇文章,本篇文章讲vuex ,如何去改变state ,actions的使用,我依然使用了vuex的modules1.设置actions
- 有用的符号:| 竖杠后的字符会被原样输出 · 点表示下一级的所有字符都会被原样输出,不再被识别。(就是|的升级版,实现批量) include
- 一、前言其实,在开发过程中,虽然我们没有直接使用到描述符,但是它在底层却无时不刻地被使用到,例如以下这些:function、bound me
- innewDropList = [9,10,11,12,22,50,51,60,61]newDB = newDB[newDB['gr
- 使用python进行基本的图像操作与处理前言:与早期计算机视觉领域多数程序都是由 C/C++ 写就的情形不同。随着计算机硬件速度越来越快,研
- 概述laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造。因为使用了服务容器,laravel中大部分
- 一、数据集小企鹅数据集,提取码:1234该数据集一共包含8个变量,其中7个特征变量,1个目标分类变量。共有150个样本,目标变量为 企鹅的类
- 十个免费的web前端开发工具网络技术发展迅速,部分技术难以保持每年都有新的工具出现,这同时也意味着许多旧的工具倒在了新技术的发展之路上。前端
- 本文实例为大家分享了python批量梯度下降算法的具体代码,供大家参考,具体内容如下问题:将拥有两个自变量的二阶函数绘制到空间坐标系中,并通
- 测试把txt文件导入至mysql数据库中: table: txt文件:D:/data.txt (txt文件下载)txt中使用 '\N
- 或许你也经历过,很多人都说一个女人很漂亮,而你觉得很一般。有时候,我也尝试理解为什么会对某个女人情有独钟。通常,我用迷人来描述,但这个&qu
- Hello,Everyone!Python是个好东西!好吧,以黎某人这寒碜的赞美之词,实在上不了台面,望见谅。那我们直接来上干货吧。第一步:
- 我这里只讲几点有关于MySQL数据库安装后遇到的个别问题 我之前安装过MYSQL好像不用手动启动服务,具体也忘记了,但我上回给公司安装的那个
- drop方法有一个可选参数inplace,表明可对原数组作出修改并返回一个新数组。不管参数默认为False还是设置为True,原数组的内存值
- eWebEditor V2.80最终版 说明 目录结构说明 =============================
- 前言大家都知道,一般情况下,输入框的密码我们是看不到密码的,只有当我们点击查看密码的小图标时,密码才会显现出来,实现起来也非常简单,通过点击
- 本文实例为大家分享了微信小程序实现搜索框功能的具体代码,供大家参考,具体内容如下效果:wxml文件:<view class="
- Tensorflow二维、三维、四维矩阵运算(矩阵相乘,点乘,行/列累加)1. 矩阵相乘 根据矩阵相乘的匹配原则,左乘矩阵的列数要等于右乘矩