Python实现多进程:multiprocessing.Process进程类详解
使用场景
IO操作不占用CPU(从硬盘、网络、内存读数据都算IO)
计算占用CPU(如计算1+1)
Python中的线程是假线程,不同线程之间的切换是需要耗费资源的,因为需要存储线程的上下文,不断的切换就会耗费资源
Python多线程适合IO操作密集型的任务(如socket server网络并发这一类的)
Python多线程不适合CPU密集操作型的任务,主要使用CPU来计算,如大量的数学计算
那么如果有CPU密集型的任务怎么办?可以通过多进程来操作(不是多线程)
假如CPU有8核,每核CPU都可以运行1个进程,每个进程可以用1个线程来进行计算
进程之间不需要使用GIL锁,因为进程是独立的,不会共享数据
进程可以开启很多个,但是8核CPU同时只能对8个任务进行操作
1. 导包进程包
import multiprocessing
2. 创建子进程
sub_process = multiprocessing.Process(group, target, name, args, kwargs, *, daemon)
- group:指定进程组,目前只能使用None
- target:执行的目标任务名
- name:进程名字
- args:以元组方式给执行任务传参
- kwargs:以字典方式给执行任务传参
- daemon:是否设置为守护进程
关于守护进程:
1.守护进程会在主进程代码执行结束后就终止
2.守护进程内无法再开启子进程,否则抛出异常AssertionError: daemonic processes are not allowed to have children
3. 进程对象常用方法
- sub_process.start():启动子进程实例(创建子进程)
- sub_process.join([timeout]):等待子进程执行结束(timeout指定主进程等待的秒数)
- sub_process.terminate():不管任务是否完成,立即终止子进程
- sub_process.is_alive():判断当前进程是否还活着
4.进程对象常用属性
- sub_process.pid:当前进程的进程号
- sub_process.name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
- sub_process.daemon:是否为守护主进程
5. 其它常用方法
- multiprocessing.current_process():获取当前进程对象
- os.getpid() :获取当前进程编号
- os.getppid():获取当前父进程编号
- os.kill(pid, 9):杀死指定编号的进程
6. 实例代码及分析
import multiprocessing
import time
# 跳舞任务
def dance():
for i in range(5):
print("跳舞中...")
time.sleep(0.2)
# 唱歌任务
def sing():
for i in range(5):
print("唱歌中...")
time.sleep(0.2)
if __name__ == '__main__':
# 创建跳舞的子进程
# group: 表示进程组,目前只能使用None
# target: 表示执行的目标任务名(函数名、方法名)
# name: 进程名称, 默认是Process-1, .....
dance_process = multiprocessing.Process(target=dance, name="myprocess1")
sing_process = multiprocessing.Process(target=sing)
# 启动子进程执行对应的任务
dance_process.start()
sing_process.start()
7.总结
进程是操作系统进行资源分配的基本单位
进程是Python程序中实现多任务的一种方式
进程之间不共享全局变量:创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本
设置守护进程(其实是守护主进程):为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁。设置守护主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行,也可以通过sub_process.terminate()方法在主进程结束前销毁子进程