every blog every motto: Light tomorrow with today.
0. 前言 网上目前关于多进程返回值的文章较为零散,本文主要进行简单的小结。
说明:
- 其中被测试函数的函数返回值作为函数参数。所以使用多进程运行时间并没有减少,反而更慢,这是需要说明的,关于运行时间,仅作一般结果进行展示,不是本文的重点。
- 其中关于apply和apply_async两种方法运行时间的比较可参考时间比较
【【python】多进程返回值比较】导入模块:
import threading
from queue import Queue
import multiprocessing
from multiprocessing import Manager
import timeloop_number = 30000 # 循环次数
1.1 无多进程情况
def fun(k):
"""被测试函数"""
print('-----fun函数,参数为{}----'.format(k))
m = k + 10
return m
@count_time
def call_fun():
"""没有使用多线/进程的情况"""
number = 0for i in range(loop_number):
print('number:{}'.format(number))
number = fun(number)def main():
"""主程序"""# 1. 没有使用多线程
call_fun()if __name__ == '__main__':
main()
结果:
文章图片
1.2 多进程返回值 1.2.1 方法一:进程池Pool
有关多种进程池的apply,apply_async的时间比较可参考文献1
1. apply
def fun(k):
"""被测试函数"""
print('-----fun函数,参数为{}----'.format(k))
m = k + 10
return m@count_time
def my_process():
"""多进程"""# 方法一:apply/apply_async
pool = multiprocessing.Pool(4)# 创建4个进程
k = 0
for i in range(loop_number):
k = pool.apply(fun, args=(k,)
print('返回值为:', k)
def main():
"""主程序"""# 3. 使用多进程
my_process()if __name__ == '__main__':
main()
结果:
文章图片
2. apply_async
def fun(k):
"""被测试函数"""
print('-----fun函数,参数为{}----'.format(k))
m = k + 10
return m@count_time
def my_process():
"""多进程"""# 方法一:apply/apply_async
pool = multiprocessing.Pool(4)# 创建4个进程
k = 0
for i in range(loop_number):
k = pool.apply_async(fun, args=(k,))
k = k.get()
print('返回值为:', k)
def main():
"""主程序"""# 3. 使用多进程
my_process()if __name__ == '__main__':
main()
结果:
文章图片
说明:
上述运行时间,仅作一般参考,运行时间非本文重点,具体参考文献1
小结:
- 因为测试函数的特殊性(函数返回值作为参数传递进函数),两种方法都相当于串行,所以时间方面并没差距
- apply_async方法返回结果为对象,所以需要用get方法获取结果
@count_time
def my_process():
"""多进程"""# 方法一:apply/apply_async
pool = multiprocessing.Pool(4)# 创建4个进程
k = 0
for i in range(loop_number):
t = pool.apply_async(fun, args=(k,))print('返回值为:', t.get())
结果:
文章图片
2. 返回结果最后输出:
@count_time
def my_process():
"""多进程"""# 方法一:apply/apply_async
pool = multiprocessing.Pool(4)# 创建4个进程
k = 0
li = [] # 空列表
for i in range(loop_number):
t = pool.apply_async(fun, args=(k,))
li.append(t)
for i in li:
print('返回值为:', i.get())
结果:
文章图片
时间不同的原因:
在进行得到各个结果的时候,是将结果追加到列表中,否则,在得到结果get的时候会阻塞进程,从而将多进程变成了单进程,当使用列表来存放时,在进行get数据的时候,可以设置超时时间,如,get(timeout=5)。小结:
- 对于apply_async返回结果最后输出时间更短
- 对于apply二者没有明显区别,读者可自行验证
from multiprocessing import Manager, Processdef fun(k,result_dict):
"""被测试函数"""
print('-----fun函数内部,参数为{}----'.format(k))
m = k + 10result_dict[k] = m # 方法二:manger@count_time
def my_process():
"""多进程"""# 方法二:Manger
manger = Manager()
result_dict = manger.dict()# 使用字典
jobs = []for i in range(10):
p = Process(target=fun, args=(i, result_dict))
jobs.append(p)
p.start()for pr in jobs:
pr.join()
var = result_dict
print('返回结果', var.values())def main():
"""主程序"""# 3. 使用多进程
my_process()if __name__ == '__main__':
main()
结果:
文章图片
说明:
- 上面用的是字典,也可以用列表
- 返回的结果只有等所有子进程运行完以后才能获取,从这一点上来说,不满足我们的要求,由于作为获取多进程的一种方法,附上。
定义类
class MyProcess(multiprocessing.Process):
def __init__(self, name, func, args):
super(MyProcess, self).__init__()
self.name = name
self.func = func
self.args = args
self.res = ''def run(self):
self.res = self.func(*self.args)
def fun(k,p):
"""被测试函数"""
print('-----fun函数内部,参数为{}----'.format(k))
m = k + 10p.send(m)@count_time
def my_process():
"""多进程"""# 方法三:
process_li = []
parent_con, child_con = multiprocessing.Pipe()
for i in range(30):
p = MyProcess('proce', fun, (1, child_con))
process_li.append(p)
p.start()
for i in process_li:
i.join()
for i in process_li:
print(parent_con.recv())
结果:
文章图片
说明:
- 当参数loop_number=30000时,内存溢出,电脑被搞黑屏了,所以仅循环30次,
- 函数返回的结果只能最后一起输出,不符合要求。
定义类
class MyProcess(multiprocessing.Process):
def __init__(self, name, func, args):
super(MyProcess, self).__init__()
self.name = name
self.func = func
self.args = args
self.res = ''def run(self):
self.res = self.func(*self.args)
def fun(k, p):
"""被测试函数"""
print('-----fun函数内部,参数为{}----'.format(k))
m = k + 10p.put(m)@count_time
def my_process():
"""多进程"""# 方法四:Queue
process_li = []
q = multiprocessing.Queue()
k = 1
for i in range(30):
p = MyProcess('proce', fun, (k, q))
p.start()
process_li.append(p)
for i in process_li:
i.join()while q.qsize() > 0:
print(q.get())
结果:
文章图片
说明:
- 和上面Pipe一样,内存溢出,其结果只能放在队列当中,只能最后取得,不满足需求
- 建议使用进程池apply / apply_async
- 参照这篇文章apply/apply_async时间比较分析,推荐使用ThreadPool下的apply_async
[2] https://zhidao.baidu.com/question/246068963774450124.html
[3] https://blog.csdn.net/sunt2018/article/details/85336408
[4] https://blog.csdn.net/ztf312/article/details/80337255
[5] https://www.jb51.net/article/86412.htm
[6] https://blog.csdn.net/littlehaes/article/details/102626610
推荐阅读
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍
- java|微软认真聆听了开源 .NET 开发社区的炮轰( 通过CLI 支持 Hot Reload 功能)