python多进程及进程池详解及语法实现

进程

程序与进程的区别
程序:代码 二进制 exe 静态
进程:程序运行后 资源+代码 动态
进程的流程:
在这里插入图片描述

写时拷贝:
进程中,子进程修改时拷贝影响的代码资源,不修改时不拷贝仅运行
创建进程流程:

# 导入进程模块
import multiprocessing

# 创建一个进程的实力对象
P = multiprocessing.Process(target=func_name[,args=(元组), kwargs={字典}])

# 创建并启动进程
p.start()

p.join(5)

创建进程示例:

import time
import multiprocessing

def test1():
    while True:
        print("---1---")
        time.sleep(1)
        
def test2():
    while True:
        print("---2---")
        time.sleep(1)

def main():
    p1 = multiprocessing.Process(target=test1)
    p2 = multiprocessing.Process(target=test2)
    p1.start()
    p2.start()

if __name__ == '__main__':
    main()

注:

  • 先有主进程,后有子进程,但之后谁先进行不一定,最后主进程收尾
    主线程结束,所有子线程结束;
  • 主进程结束,不影响子进程,且终端也不再能控制子进程;父进程被结束后分配继父进程,继父进程被结束后,子进程成为僵尸变量,且系统崩溃。

获取pid:

  • 当前进程pid os.getpid
  • 父进程pid os.getppid
    传递参数:
    在这里插入图片描述

注:

  • 先有进行再有线程,线程依赖于进程
  • 主进程一定有一个主线程
    进程套线程
    (类比树 主干主进程 枝干子进程 叶柄主线程 叶片子线程)
  • 进程:多份资源,各一份执行,是资源分配的单位
  • 线程:一份资源,多份执行,是操作系统调动的单位 资源占用少 推荐

进程间通信:

文件 储存中
socket 网络中
Queue队列 内存中 解耦 (multiprocessing)

Queue队列完成进程间通信流程:

# 创建一个队列
q = multiprocessing.Queue(3)  # 3代表队列中最多可以接收三条消息

# 向队列中添加数据
q.put(data)


# 从队列中取数据
q.get()

# 判断队列中是否为空
q.empty()

# 判断队列中是否已满
q.full()

注意:如果是通过进程池创建的进程,那么队列的使用要用
multiprocessing.Manager().Queue()的方式,否则会报错。

Queue创建示例:

import multiprocessing

def download_from_web(q):
    """下载数据"""
    # 模拟从网上下载的数据
    data = [11,22,33,44]

    # 向队列中写入数据
    for temp in data:
        q.put(temp)

    print("--下载器已完成下载并存入队列中--")

def analysis_data(q):
    """数据处理"""
    waitting_analysis_data =  list()
    
    # 从队列中获取数据
    while True:
        data =q.get()
        waitting_analysis_data.append(data)

        if q.empty():
            break

    # 模拟数据处理
    print(waitting_analysis_data)


def main():
    # 创建一个队列
    q = multiprocessing.Queue()

    # 创建多个进程,将队列的引用当做实参进行传参
    p1 = multiprocessing.Process(target=download_from_web,args=(q,))
    p2 = multiprocessing.Process(target=analysis_data,args=(q,))
    p1.start()
    p2.start()


if __name__ == '__main__':
    main()

进程池 pool

进程池创建流程:

# 导入进程池模块
from multiprocessing import Pool

# 定义进程池,最大进程池最大数
po = Pool(3)

# 通过进程池调用目标  apply_async非阻塞,不会等待子进程结束;apply阻塞,会等待子进程结束

po.apply_async(要调用的目标,(传递给目标的参数元祖,))

# 关闭进程池
Po.close()

# 等待进程池执行完毕
po.join()

注:

  • 主进程不会等待进程池进行完,需添加join();
    进程池若出现异常,不会显示异常。
  • 通过进程池调用目标 apply_async非阻塞,不会等待子进程结束;apply阻塞,会等待子进程结束

进程池创建演示:

from multiprocessing import Pool
import os, time, random


def worker(msg):
    t_start = time.time()
    print("%s开始执行,进程号为%d" % (msg, os.getpid()))
    # random.random()随机生成0~1之间的浮点数
    time.sleep(random.random() * 2)
    t_stop = time.time()
    print(msg, "执行完毕,耗时%0.2f" % (t_stop - t_start))


if __name__ == '__main__':

    po = Pool(3)  # 定义一个进程池,最大进程数3
    for i in range(0, 10):
        # Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
        # 每次循环将会用空闲出来的子进程去调用目标
        po.apply_async(worker, (i,))

    print("----start----")
    po.close()  # 关闭进程池,关闭后po不再接收新的请求
    po.join()  # 等待po中所有子进程执行完成,必须放在close语句之后
    print("-----end-----")

进程与线程的区别

区别:线程占用资源小,共享全局变量;进程占用资源多,每个子进程多占用一部分资源,但不共享全局变量。

优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。

猜你喜欢

转载自blog.csdn.net/weixin_44850984/article/details/89317837