详解Python中的多进程、进程间通信(队列和管道) - multiprocessing、Process、Pool、Queue、Pipe详解

其他关于Python的总结文章请访问:https://www.jianshu.com/nb/47435944

详解Python中的多进程、进程间通信(队列和管道) - multiprocessing、Process、Pool、Queue、Pipe详解

计算机执行任务都是多任务同步执行的,比如使用浏览器浏览网页是一个任务,同时使用编辑器写代码又是一个任务,计算机还有好多的后台任务,这些任务都是同时进行的。对于多核CUP来说,不同的任务可以被调度到多个核上平行进行,但是一个核上也同时进行着多个任务,在同一个核上的多个任务实机上是交替进行的,比如计算机使用0.0001秒执行一个任务,然后切换到另一个任务执行0.0001秒,如此交替运行多个任务,但是由于运算速度很快,所以让我们觉得这些任务是同时进行的。我们可以乘这些任务为进程process)。一个任务其实通常还有多个子任务同时进行,这些子任务被称之为线程thread),一个进程必定至少包括一个进程,也可以有多个线程,Python中可以使用多进程、多线程、多进程同时多线程等方式处理并行程序。

首先,每一个进程都可以使用 os.getpid() 的方法获取此进程的pid(要引入os模块),pid是进程的唯一性标识。

Python中可以使用 multiprocessing 包来处理多进程:

import multiprocessing

使用Process处理多进程

使用 Process 可以创建一个进程,Process创建进程时可以传入参数,target参数接收一个函数作为该进程要执行的内容(函数可以带参数),然后使用args参数为作为target的函数传入参数,使用元组传入,最后要留有一个逗号。

一个Process的实例有如下的一些方法:

  • start: 开始该进程
  • join:等待进程结束
  • terminate:强制结束该进程

一个例子:

from multiprocessing import Process
import os


def print_process(text):
    print("Process \n\tPID: {}\n\tTEXT: {}\n".format(os.getpid(), text))


if __name__ == "__main__":
    print("Processes Starting...")
    process1 = Process(target=print_process, args=('process 1',))
    process2 = Process(target=print_process('process 2'))
    process1.start()
    process2.start()
    process1.join()
    process2.terminate()
    print("Processes Ended")

得到的结果:

Processes Starting...
Process 
    PID: 17152
    TEXT: process 2
Process 
    PID: 16884
    TEXT: process 1
Processes Ended

使用Pool处理多进程

Pool可以用于处理大量分进程,批量管理,实例化一个Pool对象可以传入整数指定Pool中最大同时执行的进程数量,默认值为你计算机CPU的核数。如果传入的参数大于计算机的核数,也就是默认值,则需要先跑完核数个进程后才会继续执行后边的进程(比如计算机核数为8,传入9作为参数,则会先执行8个进程,有一个进程执行结束后,才会有第九个进程开始执行)

一个Pool实例的常用方法有:

  • apply_async:向进程池中添加一个进程并设置要执行的内容,可以传入一个函数做参数,然后使用args指定函数的参数,或者直接将参数写在函数后边,同理于Process的参数
  • close:关闭池,表示不会再给该进程池中添加新的进程
  • join:等待池中所有进程结束

一个例子:

from multiprocessing import Pool
import os


def print_process(text):
    print("Process \n\tPID: {}\n\tTEXT: {}".format(os.getpid(), text))


if __name__ == "__main__":
    print("Processes Pool Starting...")
    pool = Pool(2)
    for i in range(3):
        pool.apply_async(print_process(i + 1))
    print("All processes have been added into the pool")
    pool.close()
    pool.join()
    print("All processes in the pool have ended")

得到的结果:

Processes Pool Starting...
Process 
    PID: 17544
    TEXT: 1
Process 
    PID: 17544
    TEXT: 2
Process 
    PID: 17544
    TEXT: 3
All processes have been added into the pool
All processes in the pool have ended

进程间通信

进程之间进行通信依赖于操作系统提供的多种机制,这里主要详述Python中常使用的两种机制:QueuePipes,它们的区别在于:

  • Queue:队列,是先进先出的数据结构,可以供给多个写入者和多个读取者,写入者向队列的队尾写入数据,读取者从队列的队头读取数据
  • Pipes:管道,只供给于一对进程通信,两个进程在管道的两端,两个进程都可以发送给对方消息以及接受对方的消息,管道可以理解为一根网线

使用Queue通信

使用Queue创建一个队列实例,一个实例的主要方法:

  • put:向队列的队尾写入数据
  • get:从队列的队头读取数据

直接看一个例子,这个例子中我们定义两个进程,一个用来向队列中写入数据,一个用于从队列中读取数据:

from multiprocessing import Process, Queue
import os, time, random


def writer(queue):
    print("Writing process with PID {}".format(os.getpid()))
    for i in range(5):
        print("Putting {} into the queue".format(i + 1))
        queue.put(i + 1)
        time.sleep(random.random())


def reader(queue):
    print("Reading process with PID {}".format(os.getpid()))
    while True:
        get_value = queue.get()
        print("Getting {} from the queue".format(get_value))


if __name__ == "__main__":
    queue = Queue()
    writer_process = Process(target=writer(queue))
    reader_process = Process(target=reader(queue))

    reader_process.start()
    writer_process.start()

    writer_process.join()
    reader_process.terminate()  # while True, 因此不能等到其结束,只能使用terminate

使用Pipes通信

使用Pipes创建一个管道实例,一个管道实例的主要方法:

  • send:向管道中发送信息
  • recv:从管道中接收信息
  • close:关闭管道

直接看一个例子,管道两端的进程互相给对方发消息:

from multiprocessing import Pipe

if __name__ == "__main__":
    (pipe_left, pipe_right) = Pipe()

    pipe_left.send("Hello, I'm LEFT!")
    pipe_right.send("Hello, I'm RIGHT!")

    print("pipe_left received {}".format(pipe_left.recv()))
    print("pipe_right received {}".format(pipe_right.recv()))

    pipe_left.close()
    pipe_right.close()

得到的结果为:

pipe_left received Hello, I'm RIGHT!
pipe_right received Hello, I'm LEFT!

你可能感兴趣的:(详解Python中的多进程、进程间通信(队列和管道) - multiprocessing、Process、Pool、Queue、Pipe详解)