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

写在前面

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

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

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

multiprocessing(多进程)

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

import multiprocessing#进程包
import timedef start():time.sleep(2)#让程序沉睡 2 秒print(multiprocessing.current_process().name)#打印进程名字print(multiprocessing.current_process().pid)#打印pidprint(multiprocessing.current_process().is_alive())#打印进程是否活着if __name__ == "__main__":print('程序开始')p = multiprocessing.Process(target = start)#只用写函数名  不要加括号p.start()#开始p.join()#堵塞print('程序结束')

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

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

进程通信

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

from multiprocessing import Process,Queuedef write(q):#放入队列print('加入队列成功:{}'.format(Process.pid))#打印进程pidfor i in range(10):# 0~9print('往队列放入:{}'.format(i))q.put(i)#放入def read(q):#读取队列print('加入队列成功:{}'.format(Process.pid))#打印进程pidwhile 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 multiprocessingdef index_pool(data):res = data * datareturn resif __name__ == "__main__":data =  list(range(100))#100个任务 pool = multiprocessing.Pool(processes = 4)#进程池大小为4pool_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 timenumber_list = [1,2,3,4,5,6,7,8,9,10]def add_number(data):#这个函数  只能消耗CPU资源  没啥意义item = count(data)return itemdef count(number):#单纯计算  随便写for i in range(0,5000000):i = i + 1return i * numberif __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.hqwc.cn/news/292737.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ceph块存储学习

目录 ceph的组件和功能 ceph的数据读写流程 ceph存储池学习 ceph的组件和功能 Ceph OSD:功能是存储数据,处理数据的复制、恢复、平衡数据分布,并将一些相关数据提供给Ceph Monitor,。 Ceph Monitor: 功能是维护整个集群健康状态&…

C语言之初识C语言

文章目录 前言一、什么是C语言二、第一个C语言程序三、数据类型四、变量,常量1、变量1.1 变量的命名1.2 变量的分类1.3 变量的使用1.4 变量的作用域和生命周期2、变量 五、字符串1. 概念2. 求解字符串的长度【strlen】3. 转义字符【含笔试题】 六、注释七、选择语句…

20 Vue3中使用v-for遍历普通数组

概述 使用v-for遍历普通数组在真实开发中还是比较常见的。 基本用法 我们创建src/components/Demo20.vue&#xff0c;代码如下&#xff1a; <script setup> const tags ["JavaScript", "Vue3", "前端"] </script> <template…

网络安全-API接口安全

本文为作者学习文章&#xff0c;按作者习惯写成&#xff0c;如有错误或需要追加内容请留言&#xff08;不喜勿喷&#xff09; 本文为追加文章&#xff0c;后期慢慢追加 API接口概念 API接口&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&…

亚马逊撸货、撸卡怎么做成功率更高?教你解决亚马逊撸货的底层环境

在当前的跨境电商环境下&#xff0c;许多人都在从事亚马逊的撸货、撸卡业务&#xff0c;但亚马逊的风控系统非常严格&#xff0c;因此很容易被封号或订单被取消。为了提高成功率&#xff0c;我们需要采取一些措施和方法。这篇文章就来分享做亚马逊撸货、撸卡如何提高成功率&…

Leetcode—剑指Offer LCR 025.两数相加II【中等】

2023每日刷题&#xff08;六十七&#xff09; Leetcode—LCR 025.两数相加II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode…

Centos安装Docker及使用

文章目录 配置要求Centos安装Docker卸载docker&#xff08;可选&#xff09;安装docker首先需要大家虚拟机联网&#xff0c;安装yum工具然后更新本地镜像源&#xff1a;然后输入安装docker命令&#xff1a;查看docker的版本 启动docker关闭防火墙接着通过命令启动docker 配置镜…

抖店怎么运营?走通流程是关键!

我是电商珠珠 很多新手在入驻抖店的时候&#xff0c;都不知道前期怎么去运营。 运营的技巧很多&#xff0c;牵扯到很多细节&#xff0c;跑通流程是关键。 所以&#xff0c;今天就来给大家讲讲抖店的几个基本流程&#xff0c;只有将流程跑通了才能去更快的抠细节上的东西。 …

web架构师编辑器内容-创建业务组件和编辑器基本行为

编辑器主要分为三部分&#xff0c;左侧是组件模板库&#xff0c;中间是画布区域&#xff0c;右侧是面板设置区域。 左侧是预设各种组件模板进行添加 中间是使用交互手段来更新元素的值 右侧是使用表单的方式来更新元素的值。 大致效果&#xff1a; 左侧组件模板库 最初的模板…

养殖畜牧企业官网搭建的作用是什么

养殖畜牧业在市场中需求高且体系大&#xff0c;涵盖陆海空动物&#xff0c;以前主要以散养为主&#xff0c;而现在则更多是品牌性规模养殖&#xff0c;为企业或市场输送肉产品及技术支持&#xff0c;其衍生出的产品&#xff0c;尤其是值得信任养殖基地&#xff0c;是众多需求企…

24 同学聚会

出局记1&#xff0c;未出局记0 #include <iostream> using namespace::std; using std::cout; using std::cin; int main() {int num,n;cin >> num >> n;int nums[num];for(int i0; i<num; i){nums[i]0;}int t-1;for(int i0; i<num-1; i){for(int j0…

2023版本QT学习记录 -4- 更改程序的图标

———————更改图标——————— &#x1f384;在Pro文件添加字段 &#x1f388;asuna为图片名 RC_ICONS asuna.ico&#x1f384;自备图片&#xff0c;转换成ico格式 使用以下网站转换 &#x1f384;获取了ico格式的图片后放到Pro路径 ———————源码获取查看…