news 2026/10/1 11:53:55

Python multiprocessing多进程原理与应用示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python multiprocessing多进程原理与应用示例

多进程原理与应用示例

更新时间为二零一九年二月二十八日十四点三十分十五秒, 作者是牧野。

这篇文章主要介绍了多进程原理与应用, 它结合了具体的实例形式, 对基于包的多进程概念进行了详细的分析, 深入讲解了其核心原理以及相关的实际操作技巧, 有需要的用户可以参考这些内容。

本文实例主要是讲述多进程原理与应用的事情, 现在分享给大家来供大家参考, 具体内容如下:

包里面的多进程管理包, 可以利用那个对象来创建进程, 这个对象上面, 是有这些方法的, 比如说启动方法, 还有join方法, run方法, 以及启动方法。

该模块的核心功能, 就是把管理进程变得和管理线程那样轻松顺手, 因为每一个进程都拥有自己独立的GIL, 所以就不会出现进程相互争抢GIL的情况, 这样一来, 在多核CPU运行环境下, 能够把执行运行的效率给大幅度地提升上去。

这是使用这个功能的例子。

import multiprocessing

import time

import cv2

def daemon1(image):

name = multiprocessing.current_process().name

for i in range(50):

image = cv2.GaussianBlur(image, (3, 3), 1)

time.sleep(0.1)

print 'daemon1 done!

'

cv2.imshow('daemon1', image)

def daemon2(image):

name = multiprocessing.current_process().name

for i in range(50):

image = cv2.GaussianBlur(image, (3, 3), 1)

time.sleep(0.5)

print 'daemon2 done!

'

cv2.imshow('daemon2', image)

if __name__ == '__main__':

t1 = time.time()

number_kernel = multiprocessing.cpu_count()

print 'We have {0} kernels'.format(number_kernel)

p1 = multiprocessing.Process(name='daemon1',

target=daemon1,args= (cv2.imread('./p1.jpg'),))

p1.daemon = False

p2 = multiprocessing.Process(name='daemon2',

target=daemon2, args=(cv2.imread('./p2.jpg'),))

p2.daemon = False

p1.start()

p2.start()

print 'p1 is {0}'.format(p1.is_alive())

p1.terminate()

p1.join()

print 'p1 is {0}'.format(p1.is_alive())

print 'p2 is {0}'.format(p2.is_alive())

p2.join()

t2 = time.time()

print '!

!!!!!!!!!!!!!!!!!!!OK!!!!!!!!!!

!!!!!!!!!!!

'

print 'total time is {0}'.format(t2-t1)

print 'p1.exitcode = {0}'.format(p1.exitcode)

print 'p2.exitcode = {0}'.format(p2.exitcode)

“中”这里指的是一个类别, 它的作用是用来创建进程, 同时还包含了定义进程相关方法的功能, 该类所对应的构造函数形式如下:

def __init__(self, group=None, target=None, name=None, args=(), kwargs={})

这个地方的参数指的是啥意思呢?

程序解读:

在中使用pool

如果需要进行操作的是多个子进程, 那么采用进程池的方式进行统一管控, 会对每个子进程实施自动化管理, 这样的做法显然是更加便利且高效的。

from multiprocessing import Pool

import os, time

def long_time_task(name):

print 'Run task {0} ({1})'.format(name,os.getpid())

start = time.time()

time.sleep(3)

end = time.time()

print 'Task {0} runs {1:.2f} seconds.'.format(name,end - start)

if __name__=='__main__':

print 'Parent process ({0})'.format(os.getpid)

p = Pool()

for i in range(12):

p.apply_async(long_time_task, args=(i,))

print 'Waiting for all subprocesses done...'

p.close()

p.join()

print 'All subprocesses done.'

跟通过类的实例化方法来创建进程的方式不一样, Pool是借由(func,args=(args))这种办法来生成进程的。在每一个进程池里面, 能够并行处理的任务数量等于咱们这台机器上面所有CPU核心的总数目。

要是弄出来的子进程的数量超过了这个上限, 那么在同一时间里, 就只允许有那一个个数的进程在执行。只有当里面的某一个进程把活儿干完了以后, 才会去启动后续的下一个进程。

存在多个子进程, 而这些多个子进程之间需要互相通信。

在多个子进程进行通信的时候, 是需要使用到.Queue的, .Queue的特点在于它是一个消息队列。比方说存在如下需求, 也就是有一个实例表现为一个子进程向队列里边写入数据, 而另一个进程从该队列里面获取数据这样的情况。

from multiprocessing import Process, Queue

import os, time, random

def write(q):

for value in ['A', 'B', 'C']:

print 'Put {0} to queue...'.format(value)

q.put(value)

time.sleep(random.random())

def read(q):

while True:

if not q.empty():

value = q.get(True)

print 'Get {0} from queue.'.format(value)

time.sleep(random.random())

else:

break

if __name__=='__main__':

q = multiprocessing.Queue()

pw = Process(target=write, args=(q,))

pr = Process(target=read, args=(q,))

pw.start()

pw.join()

pr.start()

pr.join()

Queue的使用方法, 是这样子的。

如果在进程池Pool中尝试使用Queue, 是会出错的, 所以, 应该改用那个带有点号的.Queue才行。

from multiprocessing import Process, Queue

import os, time, random

def write(q):

for value in ['A', 'B', 'C']:

print 'Put {0} to queue...'.format(value)

q.put(value)

time.sleep(random.random())

def read(q):

while True:

if not q.empty():

value = q.get(True)

print 'Get {0} from queue.'.format(value)

time.sleep(random.random())

else:

break

if __name__=='__main__':

manager = multiprocessing.Manager()

q = manager.Queue()

p = Pool()

pw = p.apply_async(write, args=(q,))

time.sleep(2)

pr = p.apply_async(read, args=(q,))

p.close()

p.join()

if not q.empty():

print 'q is not empty...'

else:

print 'q is empty...'

print 'OK'

if not q.empty():

print 'q is not empty...'

else:

print 'q is empty...'

print 'done...'

父进程与子进程共享内存

定义普通的变量,不能实现在父进程和子进程之间共享:

import multiprocessing

from multiprocessing import Pool

def changevalue(n, a):

n = 3.14

a[0] = 5

if __name__ == '__main__':

num = 0

arr = range(10)

p = Pool()

p1 = p.apply_async(changevalue, args=(num, arr))

p.close()

p.join()

print num

print arr[:]

导致最终输出的 num 的数值, 依然是由父进程那边定义的 0, 同时 arr 的第一个元素的值, 也依旧是 0。

使用那个, 来把共享的这个对象进行创建的。

import multiprocessing

def changevalue(n, a):

n.value = 3.14

a[0] = 5

if __name__ == '__main__':

num = multiprocessing.Value('d', 0.0)

arr = multiprocessing.Array('i', range(10))

p = multiprocessing.Process(target=changevalue, args=(num, arr))

p.start()

p.join()

print num.value

print arr[:]

最终输出的结果是num这个变量的值被修改成了3.14, 而这个修改的动作发生在子进程内部。与此同时, arr数组里的第一个元素值,也被更改为了数字5。

共享内存是在那个叫做pool的地方进行使用的, 具体的情况说明如下面所说的一样。

import multiprocessing

from multiprocessing import Pool

def changevalue(n, a):

n.value = 3.14

a[0] = 5

if __name__ == '__main__':

num = multiprocessing.Value('d', 0.0)

arr = multiprocessing.Array('i', range(10))

p = Pool()

p1 = p.apply_async(changevalue, args=(num, arr))

p.close()

p.join()

print num.value

print arr[:]

更多关于相关内容感兴趣的读者可查看本站专题:《进程与线程操作技巧总结》、《数据结构与算法教程》、《函数使用技巧总结》、《字符串操作技巧汇总》、《入门与进阶经典教程》、《+MySQL数据库程序设计入门教程》及《常见数据库操作技巧汇总》

本人希望在此文本中所阐述的相关内容, 能够对各位朋友在程序设计的方面, 带来一定的、并且是有益的参考与帮助。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 11:53:49

JMeter压测脚本录制:四种方式原理、HTTPS证书与关联改造实战

Jmeter 录制压测脚本这件事,表面看只是"点几下、把业务流程走一遍",真上手就知道四种常见路子各有各的脾气:有的两分钟就能出脚本,五分钟就报证书错误;有的稳得像块石头,但光配证书就能劝退一半人…

作者头像 李华
网站建设 2026/10/1 11:53:07

基于libsvm-3.3的Matlab SVM故障诊断分类实战

简介:这份资源面向机械故障诊断与模式识别方向的学习者和研究人员,提供基于支持向量机(SVM)的故障诊断与分类预测完整Matlab源码。数据源自西储大学轴承诊断数据集,并已完成特征提取,可直接用于分类实验&am…

作者头像 李华
网站建设 2026/10/1 11:53:04

线程池核心机制与实战调优:从参数到队列选型全解析

线程池这块,可以说是JUC并发编程里面试命中率最高的考点,没有之一。工作里你用不用得上、会不会调优是一回事,但面试官几乎必问“ThreadPoolExecutor的执行流程”“核心参数怎么设置”“为什么阿里规约不推荐Executors创建线程池”这些老掉牙…

作者头像 李华
网站建设 2026/10/1 11:52:42

Faster R-CNN与YOLOv5飞机目标识别实战:从数据转换到训练推理

简介:对于希望训练飞机目标识别模型的开发者,此压缩包以FasterRCNN与YOLOv5为核心,覆盖数据准备、模型训练与验证全流程,兼顾二阶段检测与单阶段检测两种范式,适合有深度学习基础、想对比算法效果的读者。包内共616个文…

作者头像 李华
网站建设 2026/10/1 11:52:38

STAP空时自适应处理杂波抑制MATLAB仿真脚本实战解析

简介:面向雷达信号处理学习者与工程人员的空时自适应处理(STAP)MATLAB脚本包,围绕“stap_clutter_ori - 副本.m”程序,解决强杂波和干扰背景下雷达目标检测困难的问题。资源压缩包仅含1个m文件,大小约3KB&a…

作者头像 李华