深入理解Python多进程编程 multiprocessing
深入理解Python多进程编程 multiprocessing
flyfish
Python 的 multiprocessing 模块允许创建多个进程,从而可以利用多核处理器的能力来并行执行任务。这意味着程序的不同部分可以在不同的CPU核心上同时运行,极大地提高了处理效率,特别是在执行计算密集型任务时。
与多线程相比,multiprocessing 使用的是系统级的进程而不是线程。每个进程都有独立的内存空间和系统资源,而线程则共享同一个进程的内存空间。因此,在Python中(特别是由于全局解释器锁GIL的存在),对于CPU密集型任务,使用multiprocessing比多线程能更有效地利用多核CPU的优势。
进程的概念
在计算机操作系统中,进程是操作系统进行资源分配和调度的基本单位。一个进程可以包含多个线程。当使用multiprocessing模块时,可以创建新的进程,这些新进程将与主程序并行运行,并且它们各自拥有独立的内存空间。
示例代码1:单个进程打印数字
下面是一个简单的示例,演示如何使用multiprocessing模块创建一个进程来打印从1到5的数字:
import multiprocessing
import timedef print_numbers():"""打印从1到5的数字"""for i in range(1, 6):print("数字:", i)time.sleep(1) # 模拟耗时操作if __name__ == "__main__":# 创建一个新的进程process = multiprocessing.Process(target=print_numbers)# 启动进程process.start()# 等待进程完成process.join()
数字: 1
数字: 2
数字: 3
数字: 4
数字: 5
multiprocessing.Process():创建一个新的进程对象。target=print_numbers:指定该进程的目标函数为print_numbers。process.start():启动进程。process.join():等待进程结束。
示例代码2:两个进程分别打印不同字符串
下面是另一个示例,演示如何同时启动两个进程,每个进程打印不同的字符串:
import multiprocessingdef print_message(message):"""打印传入的消息"""print(f"消息: {message}")if __name__ == "__main__":# 创建两个进程process1 = multiprocessing.Process(target=print_message, args=("Hello from Process 1",))process2 = multiprocessing.Process(target=print_message, args=("Hello from Process 2",))# 启动两个进程process1.start()process2.start()# 等待两个进程都完成process1.join()process2.join()
消息: Hello from Process 1
消息: Hello from Process 2
在这个例子中,定义了一个print_message函数,它接受一个字符串参数并打印出来。然后,创建了两个进程,每个进程都调用这个函数,但传递了不同的字符串参数。通过args参数,可以向目标函数传递额外的参数。最后,启动这两个进程,并等待它们完成各自的执行。这样,就可以看到两个进程几乎同时开始工作,并打印出各自的消息。
示例3:使用 multiprocessing.Value 在多个进程中共享一个计数器
multiprocessing.Value
Value 允许多个进程共享一个值。它适用于需要在多个进程中共享简单数据类型(如整数或浮点数)的情况。
import multiprocessingdef increment(counter, lock):"""增加计数器的值"""for _ in range(1000):with lock:counter.value += 1if __name__ == "__main__":# 创建一个共享的整数值和锁counter = multiprocessing.Value('i', 0) # 'i' 表示整数类型lock = multiprocessing.Lock()# 创建多个进程来增加计数器processes = [multiprocessing.Process(target=increment, args=(counter, lock)) for _ in range(10)]# 启动所有进程for p in processes:p.start()# 等待所有进程完成for p in processes:p.join()print("最终计数器值:", counter.value)
最终计数器值: 10000
multiprocessing.Value(typecode_or_type, *args, lock=True):创建一个新的共享值对象。typecode_or_type指定了要共享的数据类型(例如'i'表示整数)。value.value:访问共享值的实际内容。lock:确保对共享资源的安全访问,防止竞态条件。
进程(Process)和线程(Thread)在Python中的区别
| 特性 | 进程(Process) | 线程(Thread) |
|---|---|---|
| 内存空间 | 每个进程有独立的内存空间 | 所有线程共享同一进程的内存空间 |
| 资源消耗 | 开销较大,需要更多系统资源 | 轻量级,开销小,资源共享 |
| 通信难度 | 进程间通信复杂(IPC),如管道、套接字等 | 线程间通信简单,直接访问相同变量和数据结构 |
| 全局解释器锁(GIL) | 不受GIL限制,适合计算密集型任务 | 受GIL限制,对于计算密集型任务效率提升有限 |
| 适用场景 | 计算密集型任务,稳定性要求高的应用 | I/O密集型任务,快速响应用户界面的应用 |
| 崩溃影响 | 一个进程崩溃不影响其他进程 | 一个线程出错可能导致整个进程崩溃 |
Python中多线程(Thread)和多进程(Process)的区别
| 特性 | 多线程(Thread) | 多进程(Process) |
|---|---|---|
| 内存空间 | 所有线程共享同一进程的内存空间 | 每个进程有独立的内存空间 |
| 资源消耗 | 轻量级,开销小,资源共享 | 开销较大,需要更多系统资源 |
| 通信难度 | 线程间通信简单,直接访问相同变量和数据结构 | 进程间通信复杂(IPC),如管道、套接字等 |
| 全局解释器锁 (GIL) | 受GIL限制,对于计算密集型任务效率提升有限 | 不受GIL限制,适合计算密集型任务 |
| 适用场景 | I/O密集型任务,快速响应用户界面的应用 | 计算密集型任务,稳定性要求高的应用 |
| 崩溃影响 | 一个线程出错可能导致整个进程崩溃 | 一个进程崩溃不影响其他进程 |
| 创建与销毁开销 | 创建和销毁开销较小 | 创建和销毁开销较大 |
| 并发性能 | 对于I/O密集型任务性能较好,但对于CPU密集型任务受限 | 对于CPU密集型任务性能较好 |
| 示例用途 | 网络请求、文件读写、GUI应用等 | 数据分析、图像处理、科学计算等 |
进程间通信
在Python的multiprocessing模块中,提供了几种常用的进程间通信(IPC)方式,包括队列(Queue)、管道(Pipe)等。这些工具允许不同的进程之间安全地传递数据。
使用 multiprocessing.Queue 实现进程间通信
Queue 是一个线程和进程安全的 FIFO 队列,非常适合用于进程间的简单数据交换。
示例代码:
import multiprocessingdef producer(queue):"""生产者函数,向队列中添加数据"""for i in range(5):queue.put(f"数据 {i}")print(f"生产者放入: 数据 {i}")def consumer(queue):"""消费者函数,从队列中取出数据"""while not queue.empty():data = queue.get()print(f"消费者获取: {data}")if __name__ == "__main__":# 创建一个队列对象queue = multiprocessing.Queue()# 创建生产者和消费者进程p1 = multiprocessing.Process(target=producer, args=(queue,))p2 = multiprocessing.Process(target=consumer, args=(queue,))# 启动进程p1.start()p2.start()# 等待两个进程完成p1.join()p2.join()
生产者放入: 数据 0
生产者放入: 数据 1
生产者放入: 数据 2
生产者放入: 数据 3
生产者放入: 数据 4
消费者获取: 数据 0
消费者获取: 数据 1
消费者获取: 数据 2
消费者获取: 数据 3
消费者获取: 数据 4
- 队列的使用:
queue.put()用于向队列中添加数据,queue.get()用于从队列中取出数据。 - 数据传递原理:生产者进程通过调用
put方法将数据放入队列,而消费者进程通过调用get方法从队列中取出数据。Queue对象是进程安全的,因此多个进程可以同时访问它而不发生冲突。
使用 multiprocessing.Pipe 实现进程间通信
Pipe 提供了一个双向通道,适用于两个进程之间的直接通信。
示例代码:
import multiprocessingdef sender(conn, messages):"""发送者函数,通过管道发送消息"""for msg in messages:conn.send(msg)print(f"发送者发送: {msg}")conn.close()def receiver(conn):"""接收者函数,通过管道接收消息"""while True:msg = conn.recv()if msg == "END":breakprint(f"接收者接收: {msg}")if __name__ == "__main__":# 创建一个管道对象parent_conn, child_conn = multiprocessing.Pipe()# 准备要发送的消息messages = ["Hello", "from", "sender", "END"]# 创建发送者和接收者进程p1 = multiprocessing.Process(target=sender, args=(child_conn, messages))p2 = multiprocessing.Process(target=receiver, args=(parent_conn,))# 启动进程p1.start()p2.start()# 等待两个进程完成p1.join()p2.join()
发送者发送: Hello
发送者发送: from
发送者发送: sender
发送者发送: END
接收者接收: Hello
接收者接收: from
接收者接收: sender
进程池的使用
multiprocessing.Pool 是一个用于管理一组工作进程的类,它可以简化并行任务的分配和结果收集。
示例代码:使用 Pool 并行计算数字的平方
import multiprocessingdef square(n):"""计算一个数的平方"""return n * nif __name__ == "__main__":# 定义要处理的数字列表numbers = [1, 2, 3, 4, 5]# 创建一个包含4个进程的进程池with multiprocessing.Pool(processes=4) as pool:# 使用map方法将square函数应用于每个数字results = pool.map(square, numbers)print("结果:", results)
结果: [1, 4, 9, 16, 25]
- 进程池的概念和作用:
Pool允许你指定一定数量的工作进程,并且可以通过map、apply等方法轻松地将任务分配给这些进程。这样可以有效地利用多核CPU来加速计算密集型任务。 - 设置进程池大小:通过
processes参数指定进程池中的工作进程数量,默认情况下,它会根据系统CPU核心数自动调整。 - 处理任务的方式:
pool.map()方法类似于内置的map()函数,但它会在多个进程中并行执行。在这个例子中,我们将square函数应用到numbers列表中的每个元素,并返回计算结果。
Semaphore(信号量)
信号量是一种更高级的同步机制,可以用来控制同时访问某一资源的进程数量。
示例:使用 Semaphore 控制并发访问
import multiprocessing
import timedef worker(semaphore, name):with semaphore:print(f"{name} 获得信号量")time.sleep(1)if __name__ == "__main__":semaphore = multiprocessing.Semaphore(3) # 最多允许3个进程同时访问processes = [multiprocessing.Process(target=worker, args=(semaphore, f"进程 {i}")) for i in range(6)]for p in processes:p.start()for p in processes:p.join()
Event(事件)
事件是一种简单的线程间通信机制,可以让一个或多个进程等待某个特定事件的发生。
示例:使用 Event 实现进程间的同步
import multiprocessing
import timedef wait_for_event(event):print("等待事件触发...")event.wait() # 阻塞直到事件被设置print("事件已触发!")def set_event(event):time.sleep(3)event.set() # 触发事件if __name__ == "__main__":event = multiprocessing.Event()p1 = multiprocessing.Process(target=wait_for_event, args=(event,))p2 = multiprocessing.Process(target=set_event, args=(event,))p1.start()p2.start()p1.join()p2.join()
Manager(管理器)
Manager 提供了更高层次的接口,可以创建可以在不同进程之间共享的数据结构,如列表、字典等。
示例:使用 Manager 创建共享数据结构
import multiprocessingdef append_to_list(shared_list, item):shared_list.append(item)print(f"添加到共享列表: {item}")if __name__ == "__main__":with multiprocessing.Manager() as manager:shared_list = manager.list() # 创建一个可共享的列表processes = [multiprocessing.Process(target=append_to_list, args=(shared_list, i)) for i in range(5)]for p in processes:p.start()for p in processes:p.join()print("最终共享列表:", list(shared_list))
文中processes = [multiprocessing.Process(target=append_to_list, args=(shared_list, i)) for i in range(5)]这一句 等于下面的代码
processes = []
for i in range(5):p = multiprocessing.Process(target=append_to_list, args=(shared_list, i))processes.append(p)
共享内存
multiprocessing 还支持通过共享内存的方式在进程之间共享数据,这对于大规模数据共享特别有用。
示例:使用 Array 共享数组
import multiprocessingdef modify_array(shared_array, index, value):shared_array[index] = valueif __name__ == "__main__":array = multiprocessing.Array('i', [1, 2, 3, 4, 5]) # 创建共享数组processes = [multiprocessing.Process(target=modify_array, args=(array, i, i*10)) for i in range(len(array))]for p in processes:p.start()for p in processes:p.join()print("修改后的数组:", list(array))
修改后的数组: [0, 10, 20, 30, 40]
相关文章:
深入理解Python多进程编程 multiprocessing
深入理解Python多进程编程 multiprocessing flyfish Python 的 multiprocessing 模块允许创建多个进程,从而可以利用多核处理器的能力来并行执行任务。这意味着程序的不同部分可以在不同的CPU核心上同时运行,极大地提高了处理效率,特别是在…...
jQuery AJAX 方法详解
jQuery AJAX 方法详解 引言 随着互联网技术的不断发展,前端开发领域的技术也在不断更新迭代。jQuery 作为一种广泛使用的前端JavaScript库,极大地简化了DOM操作和事件处理。在众多jQuery功能中,AJAX(Asynchronous JavaScript and XML)方法尤为突出,它允许我们在不重新加…...
青少年编程都有哪些比赛可以参加
Python小学生可参加的赛事: 电子学会青少年编程考级、中国计算机学会编程能力等级认证、蓝桥杯、 信奥赛CSP-J/S初赛/NOIP(推荐C)、编程设计、信息素养、科技创新赛; 升学助力(科技特长生、大学)、企业、出国留学; python比赛&am…...
sql server 数据库 锁教程及锁操作
SQL Server数据库 锁的教程 SQL Server 的数据库锁是为了保证数据库的并发性和数据一致性而设计的。锁机制能够确保多个事务不会同时修改同一数据,从而避免数据冲突和不一致的发生。理解 SQL Server 的锁机制对于开发高效、并发性强的数据库应用非常重要。 1. 锁的…...
存储结构 分类
存储结构 1,顺序存储结构 用一组地址连续的存储单元依次存储线性表的各个数据元素, 适用于频繁查询时使用。 2,链式存储结构 在计算机中用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),适用于在较…...
VSCode 中 Git 添加了多个远端,如何设置默认远端
VSCode 中 Git 添加了多个远端,如何设置默认远端 查看分支:设置默认远端手动指定远端 查看分支: * 表示当前默认远端 git branch -vv* master a1b2c3d [origin/main] Fix typo dev d4e5f6g [upstream/dev] Add feature设置默认远端 将本…...
项目中一些不理解的问题
1.Mybatis是干啥的 他是用来帮我们操作数据库的,相当于是我们的一个助手: 我们想要得到数据库中的什么数据,就可以告诉mybatis,他会给我们想要的结果,同时,我们想要对数据库做出什么操作,也可…...
vue3 + thinkphp 接入 七牛云 DeepSeek-R1/V3 流式调用和非流式调用
示例 如何获取七牛云 Token API 密钥 https://eastern-squash-d44.notion.site/Token-API-1932c3f43aee80fa8bfafeb25f1163d8 后端 // 七牛云 DeepSeek API 地址private $deepseekUrl https://api.qnaigc.com/v1/chat/completions;private $deepseekKey 秘钥;// 流式调用pub…...
Linux应用之构建命令行解释器(bash进程)
目录 1.分析 2.打印输入提示符 3.读取并且处理输入字符串 4.创建子进程并切换 5.bash内部指令 6.完整代码 1.分析 当我们登录服务器的时候,命令行解释器就会自动加载出来。接下来我们就。在命令行中输入指令来达到我们想要的目的。 我们在命令行上输入的…...
php 系统命令执行及绕过
文章目录 php的基础概念php的基础语法1. PHP 基本语法结构2. PHP 变量3.输出数据4.数组5.超全局变量6.文件操作 php的命令执行可以执行命令的函数命令执行绕过利用代码中命令(如ls)执行命令替换过滤过滤特定字符串神技:利用base64编码解码的绕…...
保护大数据的最佳实践方案
在当今数字化时代,保障大数据安全的重要性再怎么强调也不为过。 随着科技的迅猛发展以及对数据驱动决策的依赖日益加深,企业必须将保护其宝贵信息置于首位。 我们将深入探讨保障大数据安全的流程,并讨论关键原则、策略、工具及技术…...
在高流量下保持WordPress网站的稳定和高效运行
随着流量的不断增加,网站的稳定和高效运行变得越来越重要,特别是使用WordPress搭建的网站。流量过高时,网站加载可能会变慢,甚至崩溃,直接影响用户体验和网站正常运营。因此,我们需要采取一些有效的措施&am…...
Redis7——基础篇(二)
前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。 基础篇: Redis(一) 接上期内容:上期完成了Redis环境的搭建。下面开始学习Redis常用命令…...
Docker 容器安装 Dify的两种方法
若 Windows 已安装 Docker,可借助 Docker 容器来安装 Dify: 一、方法一 1. 拉取 Dify 镜像 打开 PowerShell 或命令提示符(CMD),运行以下命令从 Docker Hub 拉取 Dify 的镜像(Docker Hub中找到该命令行&…...
golang常用库之-swaggo/swag根据注释生成接口文档
文章目录 golang常用库之-swaggo/swag库根据注释生成接口文档什么是swaggo/swag golang常用库之-swaggo/swag库根据注释生成接口文档 什么是swaggo/swag github:https://github.com/swaggo/swag 参考文档:https://golang.halfiisland.com/community/pk…...
docker中pull hello-world的时候出现报错
Windows下的docker中pull的时候出现下面的错误: PS C:\Users\xxx> docker pull hello-world Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connect…...
NPM环境搭建指南
NPM(Node Package Manager)是 Node.js 的包管理工具,堪称前端开发的基石。本文将手把手教你 在Mac、Windows、Linux三大系统上快速搭建NPM环境,并验证是否成功。 一、Mac系统安装NPM 方法1:通过Homebrew安装ÿ…...
【CSS进阶】常见的页面自适应的方法
在前端开发中,自适应布局(Responsive Design)是一种让网页能够适应不同屏幕尺寸、设备和分辨率的技术。常见的自适应布局方法包括 流式布局、弹性布局(Flexbox)、栅格布局(Grid)、媒体查询&…...
Linux系统配置阿里云yum源,安装docker
配置阿里云yum源 需要保证能够访问阿里云网站 可以先ping一下看看(阿里云可能禁ping,只要能够解析为正常的ip地址即可) ping mirrors.aliyun.com脚本 #!/bin/bash mkdir /etc/yum.repos.d/bak mv /etc/yum.repos.d/*.repo /etc/yum.repos…...
啥是CTF?新手如何入门CTF?网络安全零基础入门到精通实战教程!
CTF是啥 CTF 是 Capture The Flag 的简称,中文咱们叫夺旗赛,其本意是西方的一种传统运动。在比赛上两军会互相争夺旗帜,当有一方的旗帜已被敌军夺取,就代表了那一方的战败。在信息安全领域的 CTF 是说,通过各种攻击手…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
