Python 多进程编程详解

目录

一、多进程编程简介

1. 什么是多进程

2. 多进程与多线程的区别

二、Python 中的多进程编程

1. 创建进程

2. 进程间通信

3. 进程池

4. 进程同步

5. 注意事项

三、实际应用案例

四、总结


在 Python 中,多进程编程是一种提高程序运行效率的有效手段。相比于多线程编程,多进程编程可以充分利用多核 CPU 的优势,实现真正的并行计算。本文将通过通俗易懂的表达方式和丰富的代码案例,详细讲解 Python 多进程编程的基本概念、使用方法及注意事项。

一、多进程编程简介

1. 什么是多进程

多进程编程是指在一个程序中创建多个进程,每个进程拥有独立的内存空间和系统资源,通过进程间通信(IPC)来协调各个进程的执行。这种编程方式可以充分利用多核 CPU 的计算能力,提高程序的运行效率。

2. 多进程与多线程的区别

  • 内存独立性:多进程中的每个进程拥有独立的内存空间和系统资源,而多线程中的多个线程共享同一个进程的内存空间。
  • 执行方式:多进程是真正的并行执行,每个进程在独立的 CPU 核心上运行;而多线程在单个 CPU 核心上通过时间片轮转实现并发执行。
  • 资源开销:创建和销毁进程的开销较大,因为需要分配和回收系统资源;而线程的创建和销毁开销较小。
  • 安全性:多进程之间互不干扰,安全性较高;而多线程之间共享内存,容易出现数据竞争和死锁等问题。

二、Python 中的多进程编程

Python 提供了 multiprocessing 模块来实现多进程编程。这个模块提供了一个与标准库中的 threading 模块类似的接口,但它是基于进程的而非线程。

1. 创建进程

在 multiprocessing 模块中,可以使用 Process 类来创建进程。下面是一个简单的例子:

import multiprocessing
import os
import time
 
def worker():
    print(f"Worker process id: {os.getpid()}")
    time.sleep(2)
    print("Worker process finished")
 
if __name__ == "__main__":
    print(f"Main process id: {os.getpid()}")
    p = multiprocessing.Process(target=worker)
    p.start()
    p.join()  # 等待进程结束
    print("Main process finished")

在这个例子中,我们定义了一个 worker 函数,然后在主进程中创建了一个 Process 对象,并指定 worker 函数作为目标函数。调用 start 方法启动进程,调用 join 方法等待进程结束。

2. 进程间通信

进程间通信(IPC)是多进程编程中的一个重要问题。Python 提供了多种方式进行进程间通信,包括管道(Pipe)、队列(Queue)、共享内存(shared memory)等。

使用队列(Queue)进行进程间通信:

import multiprocessing
import time
 
def worker(q):
    time.sleep(2)
    q.put("Hello from worker")
 
if __name__ == "__main__":
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=worker, args=(q,))
    p.start()
    result = q.get()  # 获取进程发送的数据
    print(result)
    p.join()

在这个例子中,我们创建了一个 Queue 对象,并将其传递给工作进程。工作进程在处理完任务后,将结果放入队列中。主进程从队列中获取结果并打印出来。

使用管道(Pipe)进行进程间通信:

import multiprocessing
import time
 
def worker(conn):
    time.sleep(2)
    conn.send("Hello from worker")
    conn.close()
 
if __name__ == "__main__":
    parent_conn, child_conn = multiprocessing.Pipe()
    p = multiprocessing.Process(target=worker, args=(child_conn,))
    p.start()
    result = parent_conn.recv()  # 接收进程发送的数据
    print(result)
    p.join()

在这个例子中,我们使用 Pipe 方法创建了一个管道对象,它返回两个连接对象:parent_conn 和 child_conn。我们将 child_conn 传递给工作进程,工作进程通过 conn.send 方法发送数据。主进程通过 parent_conn.recv 方法接收数据。

3. 进程池

对于需要创建大量进程的情况,使用进程池(Pool)可以更加高效。进程池允许你限制同时运行的进程数量,并重用进程。

使用进程池:

import multiprocessing
import os
import time
 
def worker(x):
    print(f"Worker process id: {os.getpid()}, argument: {x}")
    time.sleep(2)
    return x * x
 
if __name__ == "__main__":
    with multiprocessing.Pool(processes=4) as pool:  # 创建一个包含4个进程的进程池
        results = pool.map(worker, range(10))  # 将任务分配给进程池中的进程
    print(results)

在这个例子中,我们创建了一个包含4个进程的进程池,并使用 map 方法将任务分配给进程池中的进程。map 方法会自动将任务分配给空闲的进程,并收集每个进程的结果。

4. 进程同步

在多进程编程中,有时需要确保某些操作按照特定的顺序执行,这时可以使用进程同步机制。Python 提供了 multiprocessing.Lock、multiprocessing.Semaphore、multiprocessing.Event 等同步原语。

使用锁(Lock):

import multiprocessing
import time
 
def worker(lock, x):
    with lock:  # 获取锁
        print(f"Worker {x} is working")
        time.sleep(2)
        print(f"Worker {x} finished")
 
if __name__ == "__main__":
    lock = multiprocessing.Lock()
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(lock, i))
        processes.append(p)
        p.start()
 
    for p in processes:
        p.join()

在这个例子中,我们创建了一个锁对象,并将其传递给每个工作进程。工作进程在执行关键操作前,先获取锁,确保同一时间只有一个进程可以执行这些操作。

5. 注意事项

  • 避免共享数据:尽量避免在多个进程之间共享数据,因为这会带来复杂性和潜在的问题。如果确实需要共享数据,可以使用 multiprocessing.Value 或 multiprocessing.Array 等共享内存对象。
  • 注意资源回收:确保在进程结束时正确回收资源,例如关闭文件、网络连接等。
  • 避免死锁:在使用锁、信号量等同步原语时,注意避免死锁。例如,确保每个进程在获取锁后能够释放锁。
  • 性能开销:虽然多进程可以提高程序的运行效率,但也会带来一定的性能开销。因此,在决定是否使用多进程时,需要权衡利弊。

三、实际应用案例

下面是一个使用多进程进行图像处理的简单示例。假设我们有一个包含多张图像的文件夹,需要对每张图像进行某种处理(例如缩放)。我们可以使用多进程来提高处理速度。

import multiprocessing
import os
from PIL import Image
 
def process_image(file_path, output_dir):
    img = Image.open(file_path)
    img.thumbnail((128, 128))  # 缩放图像
    img_name = os.path.basename(file_path)
    img.save(os.path.join(output_dir, img_name))
 
def main(input_dir, output_dir, num_processes):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
 
    image_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.endswith(('png', 'jpg', 'jpeg'))]
 
    with multiprocessing.Pool(processes=num_processes) as pool:
        pool.starmap(process_image, [(img_file, output_dir) for img_file in image_files])
 
if __name__ == "__main__":
    input_dir = "path/to/input/images"
    output_dir = "path/to/output/images"
    num_processes = 4
    main(input_dir, output_dir, num_processes)

在这个例子中,我们定义了一个 process_image 函数来处理单个图像文件。然后在 main 函数中,我们创建了一个进程池,并使用 starmap 方法将任务分配给进程池中的进程。每个进程都会调用 process_image 函数来处理一个图像文件。

四、总结

本文详细介绍了 Python 中的多进程编程,包括基本概念、使用方法及注意事项。通过代码案例和实际应用场景,展示了如何使用多进程来提高程序的运行效率。希望这些内容能够帮助你更好地理解和应用 Python 多进程编程。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis篇--应用篇1--会话存储(session共享)

1、概述 实现Session共享是构建分布式Web应用时的一个重要需求,尤其是在水平扩展和高可用性要求较高的场景下。 在分布式服务或集群服务中往往会出现这样一个问题:用户登录A服务后可以正常访问A服务中的接口。但是我们知道,分布式服务通常都…

ip-协议

文章目录 1. 网络层2. ip协议2.1 ip协议格式2.2 网段划分基本概念网段划分的两种方式为什么要网段划分?特殊的IP地址IP地址数量不足 2.3 私有IP与公网IP2.4 路由 3. IP的分片与组装为什么要分片与组装?如何分片?如何组装? 1. 网络…

ECharts散点图-气泡图,附视频讲解与代码下载

引言: ECharts散点图是一种常见的数据可视化图表类型,它通过在二维坐标系或其它坐标系中绘制散乱的点来展示数据之间的关系。本文将详细介绍如何使用ECharts库实现一个散点图,包括图表效果预览、视频讲解及代码下载,让你轻松掌握…

Jmeter录制https请求

jmeter 5.5版本,chrome浏览器 1、首先添加Test Plan-Thread Group-HTTP(S) Test Script Recorder 2、设置HTTP(S) Test Script Recorder界面的Port(监听端口,设置浏览器代理时需要与这里保持一致)、HTPS Domains(录制…

【Git 常用操作:pull push】

Git 基本概念 Git 是一个先进的开源的分布式版本控制系统,常用于管理工作内容、项目代码等功能。 Git 工作流程 图片来源:https://www.runoob.com/git/git-basic-operations.html 说明: workspace:工作区staging area&#xff…

LLaMA-Factory GLM4-9B-CHAT LoRA 指令微调实战

🤩LLaMA-Factory GLM LoRA 微调 安装llama-factory包 git clone --depth 1 https://github.com/hiyouga/LLaMA-Factory.git进入下载好的llama-factory,安装依赖包 cd LLaMA-Factory pip install -e ".[torch,metrics]" #上面这步操作会完成…

基于kraft部署kafka集群

kafka介绍 Apache Kafka 是一个开源的分布式事件流平台,被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。 Kafka是一个拥有高吞吐、可持久化、可水平扩展,支持流式数据处理等多种特性的分布式消息流处理中间件,采用分布式…

Day13 苍穹外卖项目 工作台功能实现、Apache POI、导出数据到Excel表格

目录 1.工作台 1.1 需求分析和设计 1.1.1 产品原型 1.1.2 接口设计 1.2 代码导入 1.2.1 Controller层 1.2.2 Service层接口 1.2.3 Service层实现类 1.2.4 Mapper层 1.3 功能测试 1.4 代码提交 2.Apache POI 2.1 介绍 2.2 入门案例 2.2.1 将数据写入Excel文件 2.2.2 读取Excel文…

Web前端基础知识(三)

表单的应用非常丰富&#xff0c;可以说&#xff0c;每个网站都会用到表单。下面首先介绍表单中的form标签。 --------------------------------------------------------------------------------------------------------------------------------- <form></form&g…

NLP中的神经网络基础

一&#xff1a;多层感知器模型 1&#xff1a;感知器 解释一下&#xff0c;为什么写成 wxb>0 &#xff0c;其实原本是 wx > t ,t就是阈值&#xff0c;超过这个阈值fx就为1&#xff0c;现在把t放在左边。 在感知器里面涉及到两个问题&#xff1a; 第一个&#xff0c;特征提…

docker安装MySQL--宝塔面板操作版

记录 1 在centos中安装宝塔面板 参照宝塔面板官方网页上步骤进行操作&#xff0c;然后登录网页地址 成功后直接拉取 成功后可以在本地镜像中看到 2 创建配置文件 cd /home/mysql/conf vim my.cnf [rootplmomn-gw conf]# cat /home/mysql/conf/my.cnf [client] #设置客户端…

C++简明教程(3)(初识VS)

一、编程工具大揭秘——IDE 当我们准备踏入 C 编程的奇妙世界时&#xff0c;首先要认识一个重要的“魔法盒子”——集成开发环境&#xff08;IDE&#xff09;。IDE 就像是一个全能的编程工作室&#xff0c;它把我们写代码所需要的各种工具都整合到了一起&#xff0c;让编程这件…

电脑出现 0x0000007f 蓝屏问题怎么办,参考以下方法尝试解决

电脑蓝屏是让许多用户头疼的问题&#xff0c;其中出现 “0x0000007f” 错误代码更是较为常见且棘手。了解其背后成因并掌握修复方法&#xff0c;能帮我们快速恢复电脑正常运行。 一、可能的硬件原因 内存问题 内存条长时间使用可能出现物理损坏&#xff0c;如金手指氧化、芯片…

分布式调度框架学习笔记

一、分布式调度框架的基本设计 二、线程池线程数量设置的基本逻辑 cpu是分时复用的方法&#xff0c;线程是cpu调度的最小单元 如果当前cpu核数是n&#xff0c;计算密集型线程数一般设为n&#xff0c;io密集型(包括磁盘io和网络io)线程数一般设置为2n. 计算密集型线程数一般设…

快速排序算法 -- 深入研究

一 . 快排性能的关键点分析 快排性能的关键点分析 : 决定快排性能的关键点是每次单趟排序后 &#xff0c; key 对数组的分割 &#xff0c; 如果每次选key 基本二分居中&#xff0c;那么快排的递归树就是颗均匀的满二叉树&#xff0c;性能最佳。但是实际中虽然不可能每次都是二…

ORA-65198 PDB clone 时 不能新加datafile 以及hang的一个原因

create pluggable database XX from SS keystore identified by "YYY" parallel 32 service_name_convert( _srv, _srv); 20TB 4小时 update /* rule */ undo$ set name:2,file#:3,block#:4,status$:5,user#:6,undosqn:7,xactsqn:8,scnbas:9,scnwrp:10,inst#:11,…

Android--java实现手机亮度控制

文章目录 1、开发需求2、运行环境3、主要文件4、布局文件信息5、手机界面控制代码6、debug 1、开发需求 需求&#xff1a;开发一个Android apk实现手机亮度控制 2、运行环境 Android studio最新版本 3、主要文件 app\src\main\AndroidManifest.xml app\src\main\res\layou…

HarmonyOS NEXT 实战之元服务:静态案例效果--- 日出日落

背景&#xff1a; 前几篇学习了元服务&#xff0c;后面几期就让我们开发简单的元服务吧&#xff0c;里面丰富的内容大家自己加&#xff0c;本期案例 仅供参考 先上本期效果图 &#xff0c;里面图片自行替换 效果图1完整代码案例如下&#xff1a; import { authentication } …

一起学Git【番外篇:如何在Git中新建文件】

在介绍Git之前&#xff0c;我们需要了解一下如何在Git里添加、编辑和删除文件。 首先&#xff0c;需要使用文件编辑器进行文件的创建&#xff0c;常见的文件编辑器有以下几种&#xff1a; Vim&#xff1a;一种基于命令行的编辑器&#xff0c;功能强大&#xff0c;适合开发者和…

叉车作业如何确认安全距离——UWB测距防撞系统的应用

叉车在工业环境中运行&#xff0c;常常需要在狭窄的空间内完成货物的搬运和堆垛&#xff0c;这对操作员的技术水平和安全意识提出了极高的要求。传统的叉车作业依赖操作员的经验和视觉判断来确认安全距离&#xff0c;然而这种方式往往存在误差&#xff0c;特别是在视线受阻或光…