Python使用多进程运行含有任意个参数的函数


Posted in Python onMay 02, 2020

1. 问题引出

许多时候,我们对程序的速度都是有要求的,速度自然是越快越好。对于Python的话,一般都是使用multiprocessing这个库来实现程序的多进程化,例如:

我们有一个函数my_print,它的作用是打印我们的输入:

def my_print(x):
print(x)

但是我们嫌它的速度太慢了,因此我们要将这个程序多进程化:

from multiprocessing import Pool
 
def my_print(x):
  print(x)
 
if __name__ == "__main__":
  x = [1, 2, 3, 4, 5]
  pool = Pool()
  pool.map(my_print, x)
  pool.close()
  pool.join()

很好,现在速度与之前的单进程相比提升非常的快,但是问题来了,如果我们的参数不只有一个x,而是有多个,这样能行吗?比如现在my_print新增一个参数y:

def my_print(x, y):
print(x + y)

查看pool.map的函数说明:

def map(self, func, iterable, chunksize=None):
  '''
  Apply `func` to each element in `iterable`, collecting the results
  in a list that is returned.
  '''
  return self._map_async(func, iterable, mapstar, chunksize).get()

发现函数的参数是作为iter传进去的,但是我们现在有两个参数,自然想到使用zip将参数进行打包:

if __name__ == "__main__":
  x = [1, 2, 3, 4, 5]
  y = [1, 1, 1, 1, 1]
  zip_args = list(zip(x, y))
  pool = Pool()
  pool.map(my_print, zip_args)
  pool.close()
  pool.join()

可是执行后却发现,y参数并没有被传进去:

Python使用多进程运行含有任意个参数的函数

那么如何传入多个参数呢?这也就是本文的重点,接着往下看吧。

2. 解决方案

2.1 使用偏函数(partial)

偏函数有点像数学中的偏导数,可以让我们只关注其中的某一个变量而不考虑其他变量的影响。上面的例子中,Y始终等于1,那么我们在传入参数的时候,只需要考虑X的变化即可。

例如你有一个函数,该函数有两个参数a,b,a是不同路径的下的图片的路径,b是输出的路径。很明显,a是一直在变化的,但是因为我们要将所有图片保存在同一个文件夹下,那么b很可能一直都没变。

具体如下:

if __name__ == '__main__':# 多线程,多参数,partial版本
  x = [1, 2, 3, 4, 5]
  y = 1
 
  partial_func = partial(my_print, y=y)
  pool = Pool()
  pool.map(partial_func, x)
  pool.close()
  pool.join()

2.2 使用可变参数

在Python函数中,函数可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,这就直接给我们提供了一种思路。具体如下:

def multi_wrapper(args):
  return my_print(*args)
 
def my_print(x, y):
  print(x + y)
if __name__ == "__main__": # 多线程,多参数,可变参数版本
  x = [1, 2, 3, 4, 5]
  y = [1, 1, 1, 1, 1]
  zip_args = list(zip(x, y))
 
  pool = Pool()
  pool.map(multi_wrapper, zip_args)
  pool.close()
  pool.join()

2.3 使用pathos提供的多进程库

from pathos.multiprocessing import ProcessingPool as newPool
 
if __name__ == '__main__':# 多线程,多参数,pathos版本
  x = [1, 2, 3, 4, 5]
  y = [1, 1, 1, 1, 1]
 
  pool = newPool()
  pool.map(my_print, x, y)
  pool.close()
  pool.join()

在该库的map函数下,可以看到,它允许多参数输入,其实也就是使用了可变参数:

def map(self, f, *args, **kwds):
  AbstractWorkerPool._AbstractWorkerPool__map(self, f, *args, **kwds)
  _pool = self._serve()
  return _pool.map(star(f), zip(*args)) # chunksize

2.4 使用starmap函数

if __name__ == '__main__': # 多线程,多参数,starmap版本
  x = [1, 2, 3, 4, 5]
  y = [1, 1, 1, 1, 1]
 
  zip_args = list(zip(x, y))
  pool = Pool()
  pool.starmap(my_print, zip_args)
  pool.close()
  pool.join()

3. 总结

其实在以上4种实现方法中 ,第1种方法的限制较多,如果该函数的其它参数都在变化的话,那么它就不能很好地工作,而剩下的方法从体验上来讲是依次递增的,它们都可以接受任意多参数的输入,但是第2种需要额外写一个函数,扣分;第3种方法需要额外安装pathos包,扣分;而最后一种方法不需要任何额外不择就可以完成,所以,推荐大家选择第4种方法!

以上这篇Python使用多进程运行含有任意个参数的函数就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现获取域名所用服务器的真实IP
Oct 25 Python
使用Python下载歌词并嵌入歌曲文件中的实现代码
Nov 13 Python
python实现按行切分文本文件的方法
Apr 18 Python
Flask之请求钩子的实现
Dec 23 Python
Python图像的增强处理操作示例【基于ImageEnhance类】
Jan 03 Python
python 多线程重启方法
Feb 18 Python
Python定义函数功能与用法实例详解
Apr 08 Python
python面试题小结附答案实例代码
Apr 11 Python
解决pycharm下os.system执行命令返回有中文乱码的问题
Jul 07 Python
Pytorch之Variable的用法
Dec 31 Python
Python paramiko使用方法代码汇总
Nov 20 Python
Python基础数据类型tuple元组的概念与用法
Aug 02 Python
python多进程使用函数封装实例
May 02 #Python
Python中使用filter过滤列表的一个小技巧分享
May 02 #Python
python同时遍历两个list用法说明
May 02 #Python
python多线程实现同时执行两个while循环的操作
May 02 #Python
python 实现两个线程交替执行
May 02 #Python
Python中使用threading.Event协调线程的运行详解
May 02 #Python
浅谈Python3多线程之间的执行顺序问题
May 02 #Python
You might like
PHP默认安装产生系统漏洞
2006/10/09 PHP
PHP验证码类代码( 最新修改,完全定制化! )
2010/12/02 PHP
用PHP来计算某个目录大小的方法
2014/04/01 PHP
Yii实现多按钮保存与提交的方法
2014/12/03 PHP
PHP实现留言板功能的详细代码
2017/03/25 PHP
PHP有序表查找之二分查找(折半查找)算法示例
2018/02/09 PHP
用javascript实现画板的代码
2007/09/05 Javascript
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
ExtJS Window 最小化的一种方法
2009/11/18 Javascript
JS实现兼容各浏览器解析XML文档数据的方法
2015/06/01 Javascript
jquery专业的导航菜单特效代码分享
2015/08/29 Javascript
javascript基本语法
2016/05/31 Javascript
一句jQuery代码实现返回顶部效果(简单实用)
2016/12/28 Javascript
JS字符串统计操作示例【遍历,截取,输出,计算】
2017/03/27 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
Vue-cli Eslint在vscode里代码自动格式化的方法
2018/02/23 Javascript
vue-router 源码之实现一个简单的 vue-router
2018/07/02 Javascript
如何制作一个Node命令行图像识别工具
2018/12/12 Javascript
CKEditor 4.4.1 添加代码高亮显示插件功能教程【使用官方推荐Code Snippet插件】
2019/06/14 Javascript
微信小程序实现点击空白隐藏的方法示例
2019/08/13 Javascript
wx-charts 微信小程序图表插件的具体使用
2019/08/18 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
2020/10/26 Javascript
Python读写Excel文件方法介绍
2014/11/22 Python
Linux下编译安装MySQL-Python教程
2015/02/02 Python
Python导入oracle数据的方法
2015/07/10 Python
Python实现好友全头像的拼接实例(推荐)
2017/06/24 Python
对python中for、if、while的区别与比较方法
2018/06/25 Python
对python中基于tcp协议的通信(数据传输)实例讲解
2019/07/22 Python
python实现网站用户名密码自动登录功能
2019/08/09 Python
如何获取某个日期是当月的最后一天
2013/12/05 面试题
如何写出好的Java代码
2014/04/25 面试题
《要下雨了》教学反思
2014/02/17 职场文书
年终工作总结范文2014
2014/11/27 职场文书
2014大学生学生会工作总结
2014/12/19 职场文书
CSS3 制作的彩虹按钮样式
2021/04/11 HTML / CSS
如何利用python创作字符画
2022/06/25 Python