Python编程:多进程multiprocessing

前言

前面我们了解了计算机中的多任务原理,知道了进程和线程的概念。今天就通过代码看Python中多进程是如何实现的。

Linux\Unix多进程:os.fork()

操作系统提供了一个系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

返回结果:子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用就可以拿到父进程的ID。

Python的模块封装了常见的系统调用,其中就包括,可以在Python程序中轻松创建子进程:

提示:只在系统下可以使用。Mac系统是基于Unix系统开发的,所以也支持这种写法。如果你是在系统下做的Python开发,那么运行上面代码,会报错:

由于没有调用,但Python是支持跨平台的,所以上用Python编写多进程的程序,就需要借用模块了。

跨平台多进程:multiprocessing

模块提供了一个类来代表一个进程对象。通常可导入模块:

示例:

运行结果:

提示:上面例子中方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。说白了就是,父进程的结束时间是要等子进程结束后才结束。如果不调用此方法,运行结果如下:

父进程的结束时间不再受子进程结束的影响。父进程可能在子进程结束之前就结束,也可能在子进程结束后才结束,具体情况要看各自进程的具体操作。本例中,如果不调用方法,但子进程有耗时操作,而父进程中没有耗时的操作,所以父进程优先于子进程结束了。

说明:

1,创建子进程时,只需要传入一个执行函数和函数的参数,创建一个实例,用方法启动,这样创建进程比还要简单。

2.创建子进程时,切不可这样创建:。为了方便对比,将两种写法拿出来:

参数的传入方式不同,上面例子中通过传入,形如:,而错误的写法是直接通过指定时就一起传入,形如:。

错误的创建形式虽然可以创建子进程成功,但会导致:方法无论是否调用,都会出现进程同步的现象。即:父进程的结束时间是要等子进程结束后才结束。

线程池Pool

如果要启动大量的子进程,可以用进程池的方式批量创建子进程。模块提供了一个类来代表一个进程对象。通常可导入模块:

类可以提供指定数量的进程供用户调用,当有新的请求提交到中时,如果池还没有满,就会创建一个新的进程来执行请求。如果池满,请求就会告知先等待,直到池中有进程结束,才会创建新的进程来执行这些请求。

下面介绍一下模块下的类下的几个方法:

函数原型:

该函数用于传递不定参数,同python中的apply函数一致,主进程会被阻塞直到函数执行结束(不建议使用,并且3.x以后不在出现)。

函数原型:与用法一致,但它是非阻塞的且支持结果返回后进行回调。

函数原型:

类中的方法,与内置的函数用法行为基本一致,它会使进程阻塞直到结果返回。

注意:虽然第二个参数是一个迭代器,但在实际使用中,必须在整个队列都就绪后,程序才会运行子进程。

函数原型:

与map用法一致,但是它是非阻塞的。其有关事项见。

关闭进程池pool,使其不在接受新的任务。

结束工作进程,不在处理未处理的任务。

主进程阻塞等待子进程的退出, join方法要在close或terminate之后使用。

下面我们看一个简单的类的例子:

运行结果:

对Pool对象调用方法会等待所有子进程执行完毕,调用之前必须先调用,调用之后就不能继续添加新的了。

进程间通信

之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的模块包装了底层的机制,提供了等多种方式来交换数据。

我们以为例,在父进程中创建两个子进程,一个往里写数据,一个从里读数据:

运行结果:

小结

本文主要学习了python中的多进程及实现跨平台的多进程,进程池、通过进行进程间通信。

人人懂编程ID:pythonDNA

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180810G1BQIJ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券