python -- 多进程实战

一、创建多进程的类Process

multiprocess模块提供了一个创建进程的类Process,其创建进程有以下两种方法

  • 创建一个peocess类实例,并指定目标任务函数
  • 自定义一个类并继承Process类,重写__init__()方法和run()方法

1.验证多进程执行效率

多进程方法1(定义函数的方法):
执行代码

from multiprocessing import Process
import os
import time
# 子进程要执行的代码
def task_process(delay):
    num = 0
    for i in range(delay*10000000):
        num += i
    print(f"进程id为{os.getpid()},执行完成")

if __name__ == '__main__':
    print('父进程pid为%s'% os.getpid())
    t0 = time.time()
    task_process(3)
    task_process(3)
    t1 = time.time()
    print(f'顺序执行耗时:{t1 - t0}')
    p0 = Process(target=task_process, args=(3,))
    p1 = Process(target=task_process, args=(3,))
    t2 = time.time()
    p0.start(); p1.start()
    p0.join(); p1.join()
    t3 = time.time()
    print(f"多进程执行耗时:{t3 - t2}")

执行结果:

父进程pid为12044
进程id12044,执行完成
进程id12044,执行完成
顺序执行耗时:2.6276705265045166
进程id20912,执行完成
进程id1076,执行完成
多进程执行耗时:1.5904245376586914

多进程方法2(定义类的方法):用的少

from multiprocessing import Process
import os
import time

class MyProcess(Process):
    def __init__(self,delay):
        self.delay = delay
        print(super())
        super().__init__()

    def run(self):
        num = 0
        for i in range(self.delay*10000000):
            num += i
        print(f"进程id为{os.getpid()},执行完成")

if __name__ == '__main__':
    print('父进程pid为%s'% os.getpid())
    p0 = MyProcess(3)
    p1 = MyProcess(3)
    t2 = time.time()
    p0.start()
    p1.start()
    p0.join()
    p1.join()
    t3 = time.time()
    print(f"多进程执行耗时:{t3 - t2}")

执行结果:

父进程pid为18504
<super: <class 'MyProcess'>, <MyProcess object>>
<super: <class 'MyProcess'>, <MyProcess object>>
进程id17484,执行完成
进程id16772,执行完成
多进程执行耗时:1.5922276973724365

2.了解Process类的功能

  • 首先看下Process类的函数源码

    class multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)

  • 参数说明:

    • target:表示调用对象,一般为函数,也可以是对象
    • args:表示调用对象的位置参数
    • kwargs:表示调用对象的字典
    • name:是进程的别名
    • group:这个参数不使用,可以忽略
  • Process类提供的方法如下:

    • is_alive():返回进程是否是激活的
    • join([timeout]):阻塞进程,直到进程执行完成或超时或被终止
    • run():代表进程执行的任务函数,在使用类的方法执行多进程时会使用,可以重写
    • start():激活开启进程
    • terminate():终止进程
  • Process类的属性如下:

    • authkey:字节码,进程的准秘钥
    • daemon:父进程终止后自动终止,且不能产生新进程,必须在start()之前设置
    • exitcode():退出码,进程在运行时为None,如果为-N,就表示信号N结束
    • name:获取进程的名称
    • pid:进程id

二、daemon守护进程

1、不设置daemon属性示例

不加上join()阻塞

from multiprocessing import Process
import os
import time
import sys
print(sys.version)

# 子进程要执行的代码
def task_process(delay):
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程开始")
    print(f"sleep {delay}s")
    time.sleep(delay)
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程结束")

if __name__ == '__main__':
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程开始")
    t1 = Process(target=task_process, args=(3,))
    t1.start()
    # t1.join()
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程结束")

执行结果:父进程会在子进程前面执行

3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)]
2021-05-18 17:46:21 父进程开始
2021-05-18 17:46:21 父进程结束
3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)]
2021-05-18 17:46:21 子进程开始
sleep 3s
2021-05-18 17:46:24 子进程结束

加上join()阻塞,父进程会等待子进程执行结束再执行

from multiprocessing import Process
import os
import time
import sys
print(sys.version)


# 子进程要执行的代码
def task_process(delay):
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程开始")
    print(f"sleep {delay}s")
    time.sleep(delay)
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 子进程结束")

if __name__ == '__main__':
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程开始")
    t1 = Process(target=task_process, args=(3,))
    t1.start()
    t1.join()
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} 父进程结束")

执行结果:

2021-05-18 22:19:49 父进程开始
2021-05-18 22:19:49 子进程开始
sleep 3s
2021-05-18 22:19:52 子进程结束
2021-05-18 22:19:52 父进程结束

2、设置daemon属性

  • daemon() 守护进程:子进程守护着主进程,只要主进程结束,子进程跟着结束,哪怕没执行完;主进程不结束,守护进程也不会终止(会一直处于阻塞状态等待主进程结束)

  • 注意:
    1、将子进程设置成守护进程一定要在start()前设置,否则会报错
    2、子进程跟着主进程结束,哪怕没执行完
    3、主进程不结束,守护进程也不会终止(会一直处于阻塞状态等待主进程结束)

import time
from multiprocessing import Process

def task(second):
    print(f'Process{second} is running')
    time.sleep(second)
    print(f'Process{second} is gone')

if __name__ == '__main__':
    start_time = time.time()
    p1 = Process(target=task, args=(1,))
    p2 = Process(target=task, args=(2,))
    # 设置成守护进程(必须要在start前设置,否则会报错)
    p1.daemon = True
    p1.start()
    p2.start()
    print(f'主进程runtime:{time.time() - start_time}')

执行结果:

# 输出结果:主进程执行结束,守护进程也结束,因此p1没有执行,p2进程不是守护进程,不会随着主进程的结束而结束
# 主进程runtime:0.021903276443481445
# Process2 is running
# Process2 is gone
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值