40、multiprocessing模块基本操作

并发编程 / 2021-01-12

一、multiprocessing模块

Python为我们提供了multiprocessing模块,准确来讲它是一个包它可以用来开启子进程,并在子进程中执行我们指定的任务!multiprocessing模块功能众多:支持创建进程、进程间通信、进程间共享数据、进程间同步,为此提供了Process、Queue、Pipe、Lock等组件。

1.1、Process

创建进程的方式有两种:实例化对象、继承类!注意:如果是在Windows系统环境开发,则process必须要放在if name == 'main':里面,因为Windows没有fork

1.1.1、Process语法
Process([, target[, name[, args[, kwargs]]]])  由该类实例化得到的对象,表示创建一个子进程
	target:表示调用对象(多为函数),即该子进程要执行的任务
	args:指定的参数是为target处的函数所传递的位置参数,必须为元祖形式,且有逗号
	kwargs:与上类似,为对象传递字典形式的参数
	name:子进程名字
1.1.2、实例化对象开启进程
from multiprocessing import Process
import time


def print_str(name):
    print(f'我是子进程:{name} is Studying')
    print(f'我是子进程:{name} was stoped study')


if __name__ == '__main__':
    human = Process(target=print_str, args=('sanxi', ))
    human.start()  # 启动进程,并自动调用run(),run在自定义类继承multiprocessing时须手动写
    print('我是主进程,其它都是我小弟')
    
# 执行得到结果
我是主进程,其它都是我小弟
我是子进程:sanxi is Studying
我是子进程:sanxi was stoped study
1.1.3、继承类开启进程
from multiprocessing import Process
import time
import random


class StudyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):  # 必须要命名为run
        print(f'我是子进程:{self.name} is Studying')


human1 = StudyProcess('sanxi')
human2 = StudyProcess('chrystal')
human1.start()
human2.start()
print('我是主进程,在座各位都是弟弟')

# 执行得到结果
我是主进程,在座各位都是弟弟
我是子进程:sanxi is Studying
我是子进程:chrystal is Studying
1.1.4、进程间相互隔离
from multiprocessing import Process

sanxi = 666


def print_str():
    global sanxi
    sanxi = 777  # 其实改的还是它自己进程内名称空间的sanxi
    print(f'我是子进程的snaxi:{sanxi}')


if __name__ == '__main__':
    human = Process(target=print_str)
    human.start()
    print('我是主进程的sanxi:', sanxi)
    
# 执行得到结果
我是主进程的sanxi: 666
我是子进程的snaxi:777
1.1.5、join方法

Process是并发的,但上面之所以都是主进程先打印结果是因为子进程要去实例化等一系列操作需要耗费时间,而主进程直接打印字符串速度最快所以永远先执行完毕!

Process里面有个join方法,是让主进程等待子进程结束后再运行,如下所示:

from multiprocessing import Process


def print_str(name):
    print(f'我是子进程:{name} is Studying')


if __name__ == '__main__':
    human1 = Process(target=print_str, args=('sanxi', ))
    human2 = Process(target=print_str, args=('chrystal', ))
    human1.start()
    human2.start()
    human1.join()
    human2.join()
    print('我是主进程,其它都是我小弟')
    
# 执行得到结果
我是子进程:sanxi is Studying
我是子进程:chrystal is Studying
我是主进程,其它都是我小弟

注意:join方法是让主进程阻塞,而不是子进程们;子进程只要start就开始并发了,子进程的join方法是相当于告诉主进程:老铁,等我吃完你再走!

1.1.6、获取进程ID号

os.getpid()为获取当前进程ID号,os.getppid()为获取父进程ID号

from multiprocessing import Process
import os


def print_str(name):
    print(f'我是子进程,工号是:{os.getpid()},我BOSS工号是{os.getppid()}')


if __name__ == '__main__':
    human1 = Process(target=print_str, args=('sanxi', ))
    human1.start()
    human1.join()
    print(f'我是主进程,我工号是:{os.getpid()}')
    
# 执行得到结果
我是子进程,工号是:32121,我BOSS工号是32120
我是主进程,我工号是:32120
1.1.7、Process其它方法

terminate():杀死进程,但它是异步的,不是立即结束进程;因此有配合is_alive查询是否存活时可能为true!

is_alive():判断进程是否存活

from multiprocessing import Process
import time


def print_str(name):
    print(f'我是子进程')


if __name__ == '__main__':
    human1 = Process(target=print_str, args=('sanxi', ))
    human1.start()
    human1.terminate()  # 异步
    print(human1.is_alive())  # 因为我是在Linux环境下运行,速度太快,还没来得及完全杀死就到这了。
    print(f'我是主进程')
    time.sleep(0.1)
    print(human1.is_alive())  # 这次睡了一会,再判断时进程已经被干掉了!
    
# 执行得到结果
True
我是主进程
False
世间微尘里 独爱茶酒中