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网络编程之UDP通信实例(含服务器端、客户端、UDP广播例子)
Apr 25 Python
在Python中使用poplib模块收取邮件的教程
Apr 29 Python
Python编程中time模块的一些关键用法解析
Jan 19 Python
python 爬取微信文章
Jan 30 Python
Python 中pandas.read_excel详细介绍
Jun 23 Python
python 内置模块详解
Jan 01 Python
python 实现selenium断言和验证的方法
Feb 13 Python
python数值基础知识浅析
Nov 19 Python
Python 格式化打印json数据方法(展开状态)
Feb 27 Python
Python descriptor(描述符)的实现
Nov 15 Python
Python中BeautifulSoup通过查找Id获取元素信息
Dec 07 Python
Python爬虫实战案例之爬取喜马拉雅音频数据详解
Dec 07 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程序占用多少内存(memory_get_usage)
2012/09/23 PHP
php实现四舍五入的方法小结
2015/03/03 PHP
AJAX PHP无刷新form表单提交的简单实现(推荐)
2016/09/09 PHP
php外部执行命令函数用法小结
2016/10/11 PHP
javascript 静态对象和构造函数的使用和公私问题
2010/03/02 Javascript
jQuery .tmpl(), .template()学习资料小结
2011/07/18 Javascript
浏览器兼容console对象的简要解决方案分享
2013/10/24 Javascript
avascript中的自执行匿名函数应用示例
2014/09/15 Javascript
javaScript实现滚动新闻的方法
2015/07/30 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
省市区三级联动jquery实现代码
2020/04/15 Javascript
js+css3制作时钟特效
2016/10/16 Javascript
jQuery扩展+xml实现表单验证功能的方法
2016/12/25 Javascript
详解nodejs express下使用redis管理session
2017/04/24 NodeJs
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
2017/05/25 Javascript
Vue 重置组件到初始状态的方法示例
2018/10/10 Javascript
nodejs对项目下所有空文件夹创建gitkeep的方法
2019/08/02 NodeJs
基于vue+echarts 数据可视化大屏展示的方法示例
2020/03/09 Javascript
Vue实现点击导航栏当前标签后变色功能
2020/08/19 Javascript
Vue父组件监听子组件生命周期
2020/09/03 Javascript
Python+Django在windows下的开发环境配置图解
2009/11/11 Python
Django 导出 Excel 代码的实例详解
2017/08/11 Python
Python数据结构与算法之二叉树结构定义与遍历方法详解
2017/12/12 Python
python统计字母、空格、数字等字符个数的实例
2018/06/29 Python
pyqt弹出新对话框,以及关闭对话框获取数据的实例
2019/06/18 Python
TensorFlow索引与切片的实现方法
2019/11/20 Python
使用python模拟高斯分布例子
2019/12/09 Python
猫咪家具:CatsPlay
2018/11/03 全球购物
俄罗斯在线服装店:STOLNIK
2021/03/07 全球购物
DataList 能否分页,请问如何实现?
2015/05/03 面试题
银行出纳岗位职责
2013/11/25 职场文书
入股协议书
2014/04/14 职场文书
单位工作证明范本
2015/06/15 职场文书
Redis Stream类型的使用详解
2021/11/11 Redis
Python如何快速找到多个字典中的公共键(key)
2022/04/29 Python
Nginx的gzip相关介绍
2022/05/11 Servers