Python创建进程的四种方式

Python创建进程的四种方式

百度百科
进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。


进程,首先理解进程的概念,假如我们的电脑内存大小是一定的,要开启多个软件,内存的占用就会越来越大,计算机有自己的处理方式。例如时间片轮转,优先级调度等。如果内存当前被占用大部分的空间,开启的软件过多,其他软件也要得到计算机的内存空间,这时候内存就会轮番调度。这个时间间隔是非常短暂的给人的感觉就是多个软件在一起执行。

Python中创建多进程。Python的OS模块封装了常见的系统调用,多进程的调用就是fork,可以使用python创建多进程。


1、fork创建

import os
 
pid = os.fork() # 返回值等于0时,子进程
print(pid)
if pid>0:
    print("---父进程--%d-"%os.getpid())
else:
    print("---子进程---%d-%d-"%(os.getpid(),os.getppid()))

注意,在win系统中,没有fork这个系统调用,那么如何在win系统中开启多进程呢?

2、Multiprocessing 模块 Process类

第二种创建进程的方式,是通过Multiprocessing模块中的Process类,创建Process对象,通过对象参数target=“需要执行的子进程”

from multiprocessing import Process
import time

def test(pid:str):
    while True:
        print("---%s---" % pid)
        time.sleep(1)

p1 = Process(target=test,args=('p1',))  # target参数需要执行的子进程
p2 = Process(target=test,args=('p2',))  # target参数需要执行的子进程
p1.start()  # 让这个进程开始执行test函数里的代码
p2.start()

启动程序后,打印语句交替执行

:与fork的不同点;fork不是跨平台的,在win系统中不能使用,而在win系统中使用Process对象来调用子进程需要执行的方法。通过start开启子进程;在fork中,主进程不会等待子进程的结束,而结束主进程,在Process开启的子进程中,会等待所有的子进程结束后,才会结束主进程。

3、自定义进程:通过继承Process类,创建子进程

创建子类,继承父类(Process),重写Run方法,实例化子类对象时,通过对象start开启子进程,子进程所执行的内容,就是在重写的run方法中的内容。在.start()方法时,会自动调用run方法。

from multiprocessing import Process
import time

class MyNewProcess(Process):
    def run(self):  # 重写run方法
        while True:
            print("---1----")
            time.sleep(1)

p = MyNewProcess()
p.start()  # 开启进程

while True:
    print("---main----")
    time.sleep(1)

继承父类的这种方式,底层的实现其实就是Process创建的方式。

4、进程池(非阻塞式)-Pool方法

当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态生成多个进程。
但是如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以使用multiprocessing模块中的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool时,如果池还没有满,那么就会创建一个新的进程来执行该请求;但如果池中的进程数已满,那么该请求就会等待,直到池中有进程结束,才会创建新的进程执行。

Pool方法即进程池,需要说明有几个进程同时运行。在使用apply_async方法时第一个参数是函数名,第二个参数需要输入一个元组。在示例代码中,进程池同时允许三个进程运行,另外七个进程排队等候,当第一批的三个进程执行完后,第二批的三个再执行。所以进程池相当于起到了缓冲的作用。
实际上,在进程池的方式中,父进程基本上只需要等待子进程执行(使用pool.join()进行等待),任务都是交给子进程执行的。

from multiprocessing import Pool
import time,os

# 非阻塞式进程
from random import random

def task(task_name):
    print('开始做任务啦!',task_name)
    start = time.time()

    # 使用sleep
    time.sleep(random() * 2)
    end = time.time()
    print('完成任务:{}! 耗时:{} ,进程ID:{}'.format(task_name,(end-start),os.getpid()))

# 容器
container = []

def callback_func(n):
    container.append(n)

if __name__ == '__main__':
    pool = Pool(5)

    tasks = ['听音乐','看电影','读书','看报','玩游戏','打篮球','弹钢琴']

    for t in tasks:
        pool.apply_async(task,args=(t,))

    pool.close() # 关闭进程池,不允许继续添加进程
    pool.join() # 等待进程池中的所有进程结束

    print('------'*10)
    for c in container:
        print(c)

    print('over!!!!!!!!!!')

输出结果:

开始做任务啦! 听音乐
开始做任务啦! 看电影
开始做任务啦! 读书
开始做任务啦! 看报
开始做任务啦! 玩游戏
完成任务:看报! 耗时:0.569094181060791 ,进程ID:21451
开始做任务啦! 打篮球
完成任务:看电影! 耗时:0.6920769214630127 ,进程ID:21449
开始做任务啦! 弹钢琴
完成任务:玩游戏! 耗时:0.9521348476409912 ,进程ID:21452
完成任务:打篮球! 耗时:0.6299769878387451 ,进程ID:21451
完成任务:听音乐! 耗时:1.453145980834961 ,进程ID:21448
完成任务:读书! 耗时:1.7922098636627197 ,进程ID:21450
完成任务:弹钢琴! 耗时:1.6441609859466553 ,进程ID:21449
------------------------------------------------------------
over!!!!!!!!!!

进程池的过程:
在这里插入图片描述
在这里插入图片描述

发布了50 篇原创文章 · 获赞 4 · 访问量 1359

猜你喜欢

转载自blog.csdn.net/weixin_43999327/article/details/103807116