由浅入深走进Python异步编程【多进程】(含代码实例讲解 || multiprocessing、异步进程池、进程通信)

news2025/2/4 17:54:28

写在前面

从底层到第三方库,全面讲解python的异步编程。这节讲述的是python的多线程实现,纯干货,无概念,代码实例讲解。

本系列有6章左右,点击头像或者专栏查看更多内容,陆续更新,欢迎关注。

部分资料来源及参考链接:
https://www.bilibili.com/video/BV1Li4y1j7RY/

multiprocessing(多进程)

现在让我们初步进入多进程,这个就是python的多进程包,是自带的,简单示例:

import multiprocessing#进程包
import time

def start():
   time.sleep(2)#让程序沉睡 2 秒
   print(multiprocessing.current_process().name)#打印进程名字
   print(multiprocessing.current_process().pid)#打印pid
   print(multiprocessing.current_process().is_alive())#打印进程是否活着

if __name__ == "__main__":
   print('程序开始')
   p = multiprocessing.Process(target = start)#只用写函数名  不要加括号
   p.start()#开始
   p.join()#堵塞
   print('程序结束')

此时,并不是一个进程打开多个线程,而是多个进程,所以每次执行有不同的pid。

结果如下:
在这里插入图片描述

进程通信

本身进程是无法通信的,借助别的数据结构,就可以实现进程通信了,一般是栈和队列,就像这样:

from multiprocessing import Process,Queue

def write(q):#放入队列

    print('加入队列成功:{}'.format(Process.pid))#打印进程pid

    for i in range(10):# 0~9
        print('往队列放入:{}'.format(i))
        q.put(i)#放入

def read(q):#读取队列

    print('加入队列成功:{}'.format(Process.pid))#打印进程pid

    while True:#一有东西 就马上读取
        value = q.get()#读取
        print('获取队列中的东西:{}'.format(value))


if __name__ == "__main__":
    
    #由于Python的多进程默认无法进行通信   因为是并发执行的
    #所以要借助别的数据结构 
    #一般用栈 或者 队列
    q = Queue()#实例化Queue   队列
    pw = Process(target = write,args =(q,))#创建写入进程
    pr = Process(target = read,args = (q,))#创建读取进程
    pw.start()#启动写入
    pr.start()#启动读取

    pw.join()#堵塞读取

python当中实现了栈和队列,非常方便,如果你运行上述代码,你会发现程序没有结束,读取进程它还在反复读取。这其实就和golang中的管道类似。此处可以先做了解。

进程池

可以使用map方法批量提交目标

import multiprocessing

def index_pool(data):
    res = data * data
    return res

if __name__ == "__main__":

    data =  list(range(100))#100个任务 
    pool = multiprocessing.Pool(processes = 4)#进程池大小为4

    pool_out_puts = pool.map(index_pool,data)#一次性提交大量任务
    # pool_out_puts = pool.apply(index_pool,args=(10,))#一个个提交
    pool.close()#关闭进程  不再创建进程
    pool.join()#堵塞进程
    
    print('Pool    {}'.format(pool_out_puts))

运行结果:
在这里插入图片描述

你会发现执行速度非常快

为什么进程池这么快呢?

这就是与多线程的区别,每个进程是独立的,不会受到GIL锁的控制,速度非常快

异步进程池

上述的例子中,进程是同步执行的,如何写出异步的效果呢?

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor,as_completed
import time

number_list = [1,2,3,4,5,6,7,8,9,10]

def add_number(data):#这个函数  只能消耗CPU资源  没啥意义

    item = count(data)
    return item

def count(number):#单纯计算  随便写

    for i in range(0,5000000):
        i = i + 1

    return i * number

if __name__ == "__main__":
    
    start_time = time.time()#程序启动时间

    with ProcessPoolExecutor(max_workers = 5) as t:# max_workers参数为 你要开多少个进程

        for item in number_list:#提交任务 
            t.submit(add_number,item)

        # reqs = [t.submit(add_number,item) for item in number_list]#提交任务 简洁写法
        # for req in as_completed(reqs):# 转成 可迭代对象
        #     print(req.result())#打印信息

    print('程序总耗时:{}'.format(time.time() - start_time))

由于没有GIL锁的限制,执行会非常快。

进程池和异步进程池的区别是什么呢?

在Python中,进程池(Process Pool)和异步进程池(Asyncio Process Pool)是用于并行处理任务的两种不同的机制。

进程池(Process Pool):
进程池是通过multiprocessing模块提供的一种机制,它允许你创建一组预先初始化的进程,用于执行任务。你可以将任务提交给进程池,进程池会自动分配可用的进程来执行任务。进程池可以通过Pool类来创建。
进程池适用于CPU密集型任务,可以充分利用多核处理器的并行性。它通过创建多个进程来同时执行任务,每个进程都有自己的Python解释器和GIL,因此可以实现真正的并行执行。进程池在处理大量计算密集型任务时通常具有较好的性能。

异步进程池(Asyncio Process Pool):
异步进程池是通过concurrent.futures和asyncio模块提供的一种机制,它允许在异步环境中并行处理任务。异步进程池是建立在异步编程的基础上,可以在单个线程中同时执行多个任务。
异步进程池适用于IO密集型任务,如网络请求、文件读写等。它利用异步编程的特性,通过在任务之间进行切换来提高效率,避免了线程切换的开销。异步进程池在处理大量IO密集型任务时通常具有较好的性能。

进程池和线程池处理IO密集型的任务都很快吗?

异步线程池和异步进程池的主要区别在于线程池使用的是线程,而进程池使用的是进程。

线程池:在Python中,线程是由操作系统管理的,多个线程共享同一进程的内存空间,因此线程之间的切换开销较小。线程池适用于IO密集型任务,如网络请求、文件读写等,因为在这些任务中,大部分时间都是在等待IO操作完成,线程可以在等待期间切换执行其他任务,提高效率。

进程池:进程是由操作系统管理的,每个进程都有独立的内存空间,进程之间切换的开销较大。进程池适用于CPU密集型任务,如数据处理、图像处理等,因为这些任务需要大量的计算资源,多个进程可以并行执行,提高效率。

无论是线程池还是进程池,在处理IO密集型任务时都可以提高效率。但对于CPU密集型任务,由于Python的全局解释器锁(GIL)的存在,多线程并不能真正实现并行执行,因此在这种情况下使用进程池更为合适。如果需要同时处理大量IO密集型和CPU密集型任务,可以结合使用线程池和进程池来充分利用多核资源。

为什么不直接用进程池呢?

进程会特别占用内存,能够使用线程池的场景,还是使用线程池更好。

用实例解释进程池和异步进程池的区别

以网络爬虫为例:
当使用进程池和异步进程池来实现网络爬虫项目时,它们的处理逻辑和性能表现有一些区别。

使用进程池的处理逻辑如下:

  1. 创建一个进程池对象,设置进程数为10。
  2. 将待爬取的URL列表分成若干个子任务,每个子任务包含多个URL。
  3. 使用进程池的map()方法,将子任务提交给进程池。
  4. 进程池会自动将子任务分配给空闲的进程进行处理,每个进程负责处理一个子任务。
  5. 当所有子任务都完成时,进程池会返回结果,可以通过返回的结果来获取爬取的数据。

使用异步进程池的处理逻辑如下:

  1. 创建一个异步进程池对象,设置进程数为10。
  2. 将待爬取的URL列表分成若干个子任务,每个子任务包含多个URL。
  3. 使用异步进程池的submit()方法,将每个子任务提交给异步进程池。
  4. 异步进程池会立即返回一个Future对象,表示该子任务的执行状态。
  5. 可以通过Future对象的result()方法来获取子任务的结果,如果子任务还未完成,result()方法会阻塞等待直到结果可用。
  6. 可以使用concurrent.futures.as_completed()函数来迭代Future对象,获取已完成的子任务结果。

在性能方面,异步进程池通常比进程池更快。这是因为异步进程池可以同时执行多个任务,不需要等待一个任务完成后才能执行下一个任务,从而提高了效率。而进程池则需要按顺序逐个处理任务,无法并行执行。对于IO密集型的任务,异步进程池的性能提升更为明显,因为它可以充分利用CPU等待IO的时间来执行其他任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1328446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb笔记之前端开发JQuery

一、引言 1.1 概述 jQuery是一个快速、简洁的JavaScript代码库。jQuery设计的宗旨是“Write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的 JavaScript操作方式&#xff0c…

微信小程序格创校园跑腿小程序源码v1.1.64+前端

简介: 版本号:1.1.64 – 多学校版本 本次更新内容: 订单问题修复 (无需上传小程序) 版本号:1.1.63 – 多学校版本 本次更新内容: 失物招领增加内容安全接口; 认证增加性别选…

谷歌 | Duet AI 让洞察、聚类模型和可视化变得简单

迷失在数据的海洋 我们都经历过这样的情况:淹没在数据的海洋中,努力驾驭复杂的管道,感觉数据令人头晕。管理大量充满不同工具和 Google 搜索的选项卡以及花费大量时间筛选数据和代码以创建满足您需求的模型所带来的挫败感,真的会…

elasticsearch 与 mysql的概念对比

文档 elasticsearch是面向文档存储的,可以是数据库中的一条商品数据,一个订单信息。 文档数据会被序列化为json格式后存储在elasticsearch中。 索引(Index) 索引(index):相同类型的文档的集合映射(mapping):索引中文档的字段约束信息,类似…

SoapUI、Jmeter、Postman三种接口测试工具的比较分析!

前段时间忙于接口测试,也看了几款接口测试工具,简单从几个角度做了个比较,拿出来与诸位分享一下。本文从多个方面对接口测试的三款常用工具进行比较分析,以便于在特定的情况下选择最合适的工具,或者使用自己编写的工具…

开放式耳机推荐哪款好、百元最好的蓝牙耳机

说起开放式蓝牙耳机,相信大部分小伙伴儿都不会陌生吧。与传统的封闭式耳机相比,其不仅提升了佩戴的舒适性,而且对耳朵的保护上也非常的友好。尤其是适用于那些喜欢户外运动和长途旅行佩戴的用户。不过也因为发展的比较快,开放式耳…

vscode debug c++代码

需要提前写好CMakeLists.txt 在tasks.json中写好编译的步骤,即tasks,如cmake … 和make -j 在lauch.json中配置可执行文件的路径和需要执行tasks中的哪一个任务 具体步骤: 1.写好c代码和CMakeLists.txt 2.配置tasks.json 终端–>配置任务…

无头 SEO:技术实施的 8 个基本步骤

确保您的内容在无头 CMS 环境中大放异彩。按照我们的 8 个步骤进行一流的无头 SEO。 无头内容管理系统 (CMS) 正在兴起,迅速被宜家、耐克和国家地理等大品牌采用。 那里有很多选择,而且更有可能的是,作为 SEO 专业人士…

swing快速入门(二十三)弹球小游戏

注释很详细,直接上代码 上一篇 新增内容 1. 键盘响应监听 2. 使用定时器事件更新画板 3. 定时器事件的开始与暂停 4. 弹球小游戏的坐标逻辑判断 import javax.swing.*; import java.awt.*; import java.awt.event.*;public class swing_test_19 {//创建一个窗…

即将来临的2024年,汽车战场再起波澜?

我们来简要概况一下11月主流车企的销量表现: 根据数据显示,11月吉利集团总销量29.32万辆,同比增长28%。这在当月国内主流车企中综合实力凌厉,可谓表现得体。而与吉利直接竞争的比亚迪,尽管数据未公布,但我们…

gradio 基本样式

可以在下面的网页上作测试: Gradio PlaygroundPlay Around with Gradio Demoshttps://www.gradio.app/playground1.text、checkbox、Slider import gradio as grdef greet(name, is_morning, temperature):salutation "Good morning" if is_morning e…

Arduino平台软硬件原理及使用——Arduino Uno板卡的使用

本文目录 一、Arduino平台简介 二、Arduino Uno板卡简介 三、Arduino编译器简介 四、Arduino平台结合Arduino Uno板卡的使用 一、Arduino平台简介 Arduino 是一个灵活、易于使用的开源电子平台,这个平台包含软件和硬件。 Arduino能通过各种各样的传感器来感知环境&…

Lang–Kobayashi方程实现混沌python实现混沌序列图像

Lang–Kobayashi方程描述为: 第一部分(Drive laser)是描述的驱动激光器,第二部分(Response laser)描述的是响应激光器。实验结构图如下: 虚线框表示响应激光器中的闭环配置。开环中响应激光器无…

C#电源串口调试

目的 记录串口调试的遇到的一些问题以及相应的解决方法 1.串口定义:串口是计算机与其他硬件传输数据的通道,在计算机与外设通信时起到重要作用 2.串口通信的基础知识 C#中的串口通信类 C#使用串口通信类是SerialPort(),该类使用方法是 new 一个 SerialPort对象 为S…

【大模型实践】基于文心一言的对话模型设计

文心一言(英文名:ERNIE Bot)是百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动、回答问题、协助创作,高效便捷地帮助人们获取信息、知识和灵感。文心一言从数万亿数据和数千亿知识…

Git 配置多个 SSH-Key

Git 配置多个 SSH-Key (两个都是gitee) 先看图,官网固然重要,但是不完全行(因为官网示例是一个gitee一个github),现在想是想多个都是gitee在他上面稍微更改即可 一般不对遇到这种问题&#xf…

Kylin基础知识点解析与应用探索

目录 学习目标: 学习内容: 学习时间: 学习产出: Kylin简介 什么是Kylin Kylin的历史和发展 Kylin在大数据领域的地位和作用 Kylin架构 Kylin的组成部分和模块 Kylin的工作原理和流程 Kylin与其他大数据组件的关系和集成 Kylin功能…

ffmpeg 硬件解码零拷贝unity 播放

ffmpeg硬件解码问题 ffmpeg 在硬件解码,一般来说,我们解码使用cuda方式,当然,最好的方式是不要确定一定是cuda,客户的显卡不一定有cuda,windows 下,和linux 下要做一些适配工作,最麻…

Python知识(2/20):Python基本数据类型

1. Python基本数据类型 Python 中基本的数据类型主要有整型(int)、浮点型(float)、布尔型(bool)、 字符串(str)。 1.1 整型-int 对于整数类型来说,Python 的特殊之处在…

通过navcat的ssh连接 将一个服务器当作跳板连接远程mysql

文章目录 通过ssh连接一个服务器当作跳板连接远程mysql 通过ssh连接一个服务器当作跳板连接远程mysql 简单来说 一共三台机器 windows Linux(入口) Linux(mysql) windows 可以通过ssh 私钥连接Linux(入口)…