Python多进程

2021-03-02 16:10:35 浏览数 (1)

在python中有一个multiprocessing的模块,该模块提供了一个Process类创建进程对象。因此,需要使用多进程的时候,需要导入这个包。如下:

代码语言:javascript复制
from multiprocessing import Process    #导入模块

下面是一个例子,非常简单。注释里面写的也是非常清楚的。

代码语言:javascript复制
from multiprocessing import Process     #导入多进程模块

def child1():        #实现子进程功能的函数
    print("子进程")

def child2(num):
    print(num)

def child3(num,age):
    print(num,age)

if __name__ == "__main__":      #这行语句在Windows下执行python多进程的时候必须加上,Linux可以不需要。
    '''
    在Windows下子进程会自动import启动它的文件,这就导致,在Windows下如果不加这句,那么子进程会循环创建它本身,导致子进程出现问题。
    所以,创建子进程的语句必须被这个if给包含起来。这也意味着程序会从这里开始执行。
    __name__ 是属于 python 中的内置类属性,就是它会天生就存在于一个 python 程序中,代表对应程序名称。
    当我们在运行这个代码时这个代码的 __name__ 的值为 __main__
    当自己作为模块被调用时就是自己的名字
    '''

    p1 = Process(target=child1,name="简单的进程")       #创建进程对象,target参数是指定实现子进程功能的函数;name参数是指定子进程名字。
    p2 = Process(target=child2,name="打印数字进程",args=(123,))     #args参数的内容将会被传递给target指定的函数。注意args是一个元组。当你只有一个参数的时候,那么需要加上逗号。
    p3 = Process(target=child3,name="多参数子进程",args=(456,18))   

    p1.start()   #启动子进程,把进程加入到就绪队列中,等待系统调度机制来调用该进程。
    p2.start()
    p3.start()

    p1.join()    #父进程等待子进程结束,如果不使用join(),那么父进程将不会等待子进程。
    p2.join()       #join还有一个timeout参数,可以设置等待子进程的时长。
    p3.join()

    #进程名称对于程序员而言是有用的,但是对于操作系统而言是无意义的,操作系统用来唯一标识一个进程的标志是pid
    print(p1.name)   #打印子进程名字。
    print(p2.name)  
    print(p3.name)

    print(p1.pid)   #打印pid
    print(p2.pid)
    print(p3.pid)

执行程序结果如下:

Python的全局变量在多个进程中是不共享的,进程之间的数据是独立的。这也符合进程这个概念。下面来看一个例子。

代码语言:javascript复制
from multiprocessing import Process

num = 0
def child1():
    global num      #global表明使用全局的num变量
    num = -1
    print(num)

def child2():
    global num
    num = 1
    print(num)

if __name__ == "__main__":
    p1 = Process(target=child1,name="child1")
    p2 = Process(target=child2,name="child2")
    
    p1.start()
    p2.start()
    
    p1.join()
    p2.join()

    print(num)

执行结果如下:

当然了,你也可以继承Process类来实现自己的进程类,从而实现多进程。例如下面的例子:

代码语言:javascript复制
from multiprocessing import Process

class MyProcess(Process):
    def run(self):
        print("这是新进程")

if __name__ == "__main__":
    p = MyProcess()
    p.start()

需要说明的是,当你继承Process类之后,必须重写run函数,而run函数制作的内容就是你子进程执行的代码,start()函数会去调用run函数,从而启动一个新的进程。当你需要参数的时候,那么这个类需要一个自定义的初始化函数__init__()。

Python的multiprocessing模块还提供了Pool来创建进程池,它能方便我们创建十几个或者上百个进程。

代码语言:javascript复制
from multiprocessing import Pool
import time

def task(num):
    print(num)
    time.sleep(3)

if __name__ == "__main__":
    p = Pool(5)     #创建进程池,并切并发5个进程。
    for i in range(30):         #循环创建30个进程,但是每次只同时并发5个进程。
        p.apply_async(task, args=(i,))      
    
    print("等待结束")
    p.close()       #关闭进程池
    p.join()        #join必须放在close后面。
    print("结束")

0 人点赞