Python 中的进程
什么是进程
当一段代码被运行,或者一个应用程序被运行,就会创建一个进程,以下内容来自百度百科:
“进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体”
并行与并发
每台计算机,cpu 是计算机的运算核心,多核计算机的意思就是,这台计算机上可以同时运行数量等于其核数的进程
并发执行,即 cpu 核数 < 进程数,这个时候这些进程需要操作系统中的调度算法(时间片轮转算法、优先级调度算法等)来协调
并行执行,即 cpu 核数 > 进程数,这个时候所有的进程都能得到执行,就是并行
Python 中实现多进程的三种方法
在 Python 中,想要实现多进程有三种方式:使用os
模块中的fork()
函数、使用multiProcessing
模块的Process
类、使用multiProcessing
模块中的Pool
(进程池),下面分别介绍这三种方法及他们之间的比较
使用 os.fork() 实现多进程
首先,fork()
函数只有在 Linux 或者是 类 Linux 系统中才能使用
当程序运行到这个函数时,会新创建一个进程,新的进程会从这个函数的返回值处开始执行,fork()
函数很特殊,在父进程里,fork()
的返回值为> 0
,并且这个返回值就是主进程的pid
,而在子进程中fork()
的返回值是== 0
的
在有fork()
函数的程序中,若主程序在子程序结束之前运行完,那么系统不会等待子进程结束,而是会直接结束主进程,但这并不代表子进程也会被结束,子进程此时已经是一个独立的进程,它会自己运行到结束为止
示例如下:
1 | import os |
运行结果:
1 | Son:6081 : 6079 : 5917 |
os
模块的其他常用方法:
1 | # 获取当前进程的 pid(进程号) |
使用 Process 实现多进程
multiProcessing
模块是一个在 Windows 中也可以使用的模块,它包含Process
,使用 Process 创建的进程,主进程会等待所有的子进程结束后才结束
并且,Process
可以被继承,这样也使得Process
可以被更灵活的运用,以及封装功能性代码
使用Process
创建进程的示例:
1 | from multiprocessing import Process |
运行结果:
1 | ----main---- |
创建一个类继承Process
来实现多进程的示例:
1 | from multiprocessing import Process |
运行结果:
1 | now Process is (6155) |
os.Process
的其他常用方法及属性:
1 | # 常用方法: |
使用 Pool(进程池)实现多进程
当需要创建的子进程数量不多时,可以直接利用multiprocessing
中的Process
动态生成多个进程,但如果时上百甚至上千个目标,手动的去创建进程的工作量巨大,此时可以用到multiprocessing
模块提供的Pool
方法
初始化Pool
时,可以指定一个最大进程数,当有新的请求提交到Pool
中时,如果池还没有满,那么就会创建一个新的进程来执行请求;如果进程池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中进程结束,才会请求池中的空闲进程来执行
使用Pool
实现多进程的示例:
1 | from multiprocessing import Pool |
运行结果:
1 | ---0--- |
Pool
的其他常用方法:
1 | # 非堵塞式添加进程,第一个参数为需要调用的目标,第二个参数为传递给目标参数的元组 |
三种方法的比较:
fork()
:最底层的方法,其余两种方法创建进程实际上最底层也是通过fork()来创建的,fork()
不能直接跨平台使用,只支持 Linux 或类 Linux 平台
Process
:父进程和子进程都用来执行,并且父进程会等待所有子进程结束后再结束
Pool
:Pool
方法中,父进程一般只用于等待,真正的任务都在子进程中执行
进程间通信(使用 Queue)
进程之间是没有任何关联的,可以使用队列来进行进程间的通信,这里使用的是multiProcessing
模块的Queue
和Manage
(用于线程池)
队列是一种先进先出(FIFO)的数据结构,下面是通过不断向同一个队列中输入数据和读取数据实现进程间的通信
使用 Queue(使用 Process 实现的多进程)
直接放代码:
1 | from multiprocessing import Process |
运行结果:
1 | Put A to queue... |
使用 Manage(使用 Pool 实现的多进程)
直接放代码:
1 | from multiprocessing import Manager |
运行结果:
1 | (6306) start |
一个使用多进程实现的复制文件夹的小程序
只需要输入文件夹名字,代码如下:
1 | import os |