如何使用 Python 多处理模块

本文[1]中,我们将学习如何使用多处理模块中的特定 Python 类(进程类)。我将通过示例为您提供快速概述。

什么是多处理模块?

还有什么比从官方文档中提取模块更好的方式来描述模块呢? Multiprocessing 是一个使用类似于线程模块的 API 支持生成进程的包。多处理包提供本地和远程并发,通过使用子进程而不是线程有效地回避全局解释器锁。

线程模块不是本文的重点,但总而言之,线程模块将处理一小段代码执行(轻量级且具有共享内存),而多处理模块将处理程序执行(较重且完全隔离) 。

一般来说,多处理模块提供了各种其他类、函数和实用程序,可用于处理程序执行期间执行的多个进程。如果程序需要在其工作流程中应用并行性,该模块专门设计为交互的主要点。我们不会讨论多处理模块中的所有类和实用程序,而是将重点关注一个非常具体的类,即进程类。

什么是进程类?

在本节中,我们将尝试更好地介绍进程是什么,以及如何在 Python 中识别、使用和管理进程。正如 GNU C 库中所解释的:“进程是分配系统资源的基本单位。每个进程都有自己的地址空间和(通常)一个控制线程。一个进程执行一个程序;可以让多个进程执行相同的程序程序,但每个进程在其自己的地址空间内都有自己的程序副本,并独立于其他副本执行它。”

但这在 Python 中是什么样子的呢?到目前为止,我们已经设法对进程是什么、进程和线程之间的区别进行了一些描述和参考,但到目前为止我们还没有触及任何代码。好吧,让我们改变一下,用 Python 做一个非常简单的流程示例:

#!/usr/bin/env python
import os

# A very, very simple process.
if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

这将产生以下输出:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 144112

正如您所看到的,任何正在运行的 Python 脚本或程序都是它自己的一个进程。

创建子进程

那么在父进程中生成不同的子进程又如何呢?好吧,要做到这一点,我们需要多处理模块中的 Process 类的帮助,它看起来像这样:

#!/usr/bin/env python
import os
import multiprocessing

def child_process():
    print(f"Hi! I'm a child process {os.getpid()}")

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

    # Here we create a new instance of the Process class and assign our
    # `child_process` function to be executed.
    process = multiprocessing.Process(target=child_process)

    # We then start the process
    process.start()

    # And finally, we join the process. This will make our script to hang and
    # wait until the child process is done.
    process.join()

这将产生以下输出:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 144078
Hi! I'
m a child process 144079

关于上一个脚本的一个非常重要的注意事项:如果您不使用 process.join() 来等待子进程执行并完成,那么该点的任何其他后续代码将实际执行,并且可能会变得有点难以同步您的工作流程。

考虑以下示例:

#!/usr/bin/env python
import os
import multiprocessing

def child_process():
    print(f"Hi! I'm a child process {os.getpid()}")

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

    # Here we create a new instance of the Process class and assign our
    # `child_process` function to be executed.
    process = multiprocessing.Process(target=child_process)

    # We then start the process
    process.start()

    # And finally, we join the process. This will make our script to hang and
    # wait until the child process is done.
    #process.join()

    print("AFTER CHILD EXECUTION! RIGHT?!")

该代码片段将产生以下输出:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 145489
AFTER CHILD EXECUTION! RIGHT?!
Hi! I'
m a child process 145490

当然,断言上面的代码片段是错误的也是不正确的。这完全取决于您想要如何使用该模块以及您的子进程将如何执行。所以要明智地使用它。

创建各种子进程

如果要生成多个进程,可以利用 for 循环(或任何其他类型的循环)。它们将允许您创建对所需流程的尽可能多的引用,并在稍后阶段启动/加入它们。

#!/usr/bin/env python
import os
import multiprocessing

def child_process(id):
    print(f"Hi! I'm a child process {os.getpid()} with id#{id}")

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")
    list_of_processes = []

    # Loop through the number 0 to 10 and create processes for each one of
    # them.
    for i in range(010):
        # Here we create a new instance of the Process class and assign our
        # `child_process` function to be executed. Note the difference now that
        # we are using the `args` parameter now, this means that we can pass
        # down parameters to the function being executed as a child process.
        process = multiprocessing.Process(target=child_process, args=(i,))
        list_of_processes.append(process)

    for process in list_of_processes:
        # We then start the process
        process.start()

        # And finally, we join the process. This will make our script to hang
        # and wait until the child process is done.
        process.join()

这将产生以下输出:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 146056
Hi! I'
m a child process 146057 with id#0
Hi! I'm a child process 146058 with id#1
Hi! I'
m a child process 146059 with id#2
Hi! I'm a child process 146060 with id#3
Hi! I'
m a child process 146061 with id#4
Hi! I'm a child process 146062 with id#5
Hi! I'
m a child process 146063 with id#6
Hi! I'm a child process 146064 with id#7
Hi! I'
m a child process 146065 with id#8
Hi! I'm a child process 146066 with id#9

数据通信

在上一节中,我描述了向 multiprocessing.Process 类构造函数添加一个新参数 args。此参数允许您将值传递给子进程以在函数内部使用。但你知道如何从子进程返回数据吗?

您可能会认为,要从子级返回数据,必须使用其中的 return 语句才能真正检索数据。进程非常适合以隔离的方式执行函数,而不会干扰共享资源,这意味着我们知道从函数返回数据的正常且常用的方式。在这里,由于其隔离而不允许。

相反,我们可以使用队列类,它将为我们提供一个在父进程与其子进程之间通信数据的接口。在这种情况下,队列是一个普通的 FIFO(先进先出),具有用于处理多处理的内置机制。

考虑以下示例:

#!/usr/bin/env python
import os
import multiprocessing

def child_process(queue, number1, number2):
    print(f"Hi! I'm a child process {os.getpid()}. I do calculations.")
    sum = number1 + number2

    # Putting data into the queue
    queue.put(sum)

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

    # Defining a new Queue()
    queue = multiprocessing.Queue()

    # Here we create a new instance of the Process class and assign our
    # `child_process` function to be executed. Note the difference now that
    # we are using the `args` parameter now, this means that we can pass
    # down parameters to the function being executed as a child process.
    process = multiprocessing.Process(target=child_process, args=(queue,12))

    # We then start the process
    process.start()

    # And finally, we join the process. This will make our script to hang and
    # wait until the child process is done.
    process.join()

    # Accessing the result from the queue.
    print(f"Got the result from child process as {queue.get()}")

它将给出以下输出:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 149002
Hi! I'
m a child process 149003. I do calculations.
Got the result from child process as 3

异常处理

处理异常是一项特殊且有些困难的任务,我们在使用流程模块时必须不时地完成它。原因是,默认情况下,子进程内发生的任何异常将始终由生成它的 Process 类处理。

下面的代码引发带有文本的异常:

#!/usr/bin/env python
import os
import multiprocessing

def child_process():
    print(f"Hi! I'm a child process {os.getpid()}.")
    raise Exception("Oh no! :(")

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

    # Here we create a new instance of the Process class and assign our
    # `child_process` function to be executed. Note the difference now that
    # we are using the `args` parameter now, this means that we can pass
    # down parameters to the function being executed as a child process.
    process = multiprocessing.Process(target=child_process)

    try:
        # We then start the process
        process.start()

        # And finally, we join the process. This will make our script to hang and
        # wait until the child process is done.
        process.join()

        print("AFTER CHILD EXECUTION! RIGHT?!")
    except Exception:
        print("Uhhh... It failed?")

输出结果:

[r0x0d@fedora ~]$ python /tmp/tmp.iuW2VAurGG/scratch.py
Hi! I'm process 149505
Hi! I'
m a child process 149506.
Process Process-1:
Traceback (most recent call last):
  File "/usr/lib64/python3.11/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "/usr/lib64/python3.11/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/tmp/tmp.iuW2VAurGG/scratch.py", line 7, in child_process
    raise Exception("Oh no! :(")
Exception: Oh no! :(
AFTER CHILD EXECUTION! RIGHT?!

如果您跟踪代码,您将能够注意到在 process.join() 调用之后仔细放置了一条 print 语句,以模拟父进程仍在运行,即使在子进程中引发了未处理的异常之后也是如此。

克服这种情况的一种方法是在子进程中实际处理异常,如下所示:

#!/usr/bin/env python
import os
import multiprocessing

def child_process():
    try:
        print(f"Hi! I'm a child process {os.getpid()}.")
        raise Exception("Oh no! :(")
    except Exception:
        print("Uh, I think it's fine now...")

if __name__ == "__main__":
    print(f"Hi! I'm process {os.getpid()}")

    # Here we create a new instance of the Process class and assign our
    # `child_process` function to be executed. Note the difference now that
    # we are using the `args` parameter now, this means that we can pass
    # down parameters to the function being executed as a child process.
    process = multiprocessing.Process(target=child_process)

    # We then start the process
    process.start()

    # And finally, we join the process. This will make our script to hang and
    # wait until the child process is done.
    process.join()

    print("AFTER CHILD EXECUTION! RIGHT?!")

现在,您的异常将在您的子进程内处理,这意味着您可以控制它会发生什么以及在这种情况下应该做什么。

总结

当工作和实现依赖于并行方式执行的解决方案时,多处理模块非常强大,特别是与 Process 类一起使用时。这增加了在其自己的隔离进程中执行任何函数的惊人可能性。

Reference

[1]

Source: https://developers.redhat.com/articles/2023/07/27/how-use-python-multiprocessing-module

本文由 mdnice 多平台发布

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

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

相关文章

区块链技术研究探讨

介绍 区块链技术是一种去中心化的分布式账本技术,它通过将数据存储在多个参与者之间的区块链网络中,确保数据的透明性、安全性和不可篡改性。以下是关于区块链技术的一些重要信息: 1、 工作原理:区块链是由一系列按时间顺序链接…

21.4 CSS 盒子模型

1. 边框样式 border-style属性: 指定元素的边框样式.常用属性值: - none: 无边框(默认值). - solid: 实线边框. - dotted: 点状边框. - dashed: 虚线边框. - double: 双线边框. - groove: 凹槽状边框. - ridge: 脊状边框. - inset: 内阴影边框. - outset: 外阴影边框.这些值可…

python内置类属性

class Person:"""这是一个类,功能是描述一个人的精神面貌与行为"""age 19def __init__(self, name):self.name namedef run(self):print("run")"""__dict__ : 类属性__bases__ : 类所有父类构成元组__doc…

使用SimPowerSystems并网光伏阵列研究(Simulink实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

随机流-RandomAccessFile

RandomAccessFile RandomAccessFile 基本操作案例 RandomAccessFile 基本操作 案例 import java.io.*;public class TestMain09 {public static void main(String[] args) throws Exception {insert("D:\\home\\product\\aa.txt",2,"ni");}public static…

C++:类和对象(二)

本文主要介绍:构造函数、析构函数、拷贝构造函数、赋值运算符重载、const成员函数、取地址及const取地址操作符重载。 目录 一、类的六个默认成员函数 二、构造函数 1.概念 2.特性 三、析构函数 1.概念 2.特性 四、拷贝构造函数 1.概念 2.特征 五、赋值…

TS编译选项

自动监控编译 tsc xxx.ts -w 在一个文件夹下,创建 tsconfig.json 文件,在用命令 tsc 就可以自动编译当前文件夹下的ts文件 tsconfig.json文件配置如下: {/*tsconfig.json 是ts编译器的配置文件,ts编译器可以根据它的信息来对代…

Jenkins+maven+testng+htmlreport单元自动化测试

背景说明 为了可以在jenkins自动化运行单元测试的代码,所以使用maventestng的技术结合,达到手动或者定时去执行单元测试的代码,以便提高人工运行的自动化的效率。单元通过该方案也可以套用在httpclient框架去执行测试web api接口的自动化测试…

Kubernetes 工作中常见命令总结

① configmap 文件的操作命令:命名空间为platform,configmap的名称为openapi kubectl -n platform describe configmap openapi kubectl -n platform get configmap openapi -o yaml kubectl -n platform edit configmap openapi kubectl -n platform…

撰寫自己的Python C擴展!

撰寫自己的Python C擴展! 前言spam.cheaderC函數參數參數解析函數主體生成回傳值 method table模組定義模組初始化函數拋出異常main函數完整代碼 編譯及鏈接使用gcc使用gcc Python flags使用distutils 從Python調用C函數直接import使用distutils透過ctypes調用so檔 前言 本篇…

2022年09月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里 第1题:城堡问题 1 2 3 4 5 6 7 ############################# 1 # | # | # | | # #####—#####—#—#####—# 2 # # | # # # # # #—#####—#####—#####—# 3 # | | # # # # # #—#########—#####—#—# 4 # # | | | | # # ###########…

2023高教社杯数学建模E题思路模型 - 黄河水沙监测数据分析

# 1 赛题 E 题 黄河水沙监测数据分析 黄河是中华民族的母亲河。研究黄河水沙通量的变化规律对沿黄流域的环境治理、气候变 化和人民生活的影响, 以及对优化黄河流域水资源分配、协调人地关系、调水调沙、防洪减灾 等方面都具有重要的理论指导意义。 附件 1 给出了位…

Opencv图像暗通道调优

基于雾天退化模型的去雾算法,Opencv图像暗通道调优,(清华版代码)对普通相片也有较好的调优效果,相片更通透。 结合代码实际运行效果、算法理论模型、实际代码。我个人理解,实际效果是对图像的三个颜色通道…

04架构管理之分支管理实践-一种git分支管理最佳实践

专栏说明:针对于企业的架构管理岗位,分享架构管理岗位的职责,工作内容,指导架构师如何完成架构管理工作,完成架构师到架构管理者的转变。计划以10篇博客阐述清楚架构管理工作,专栏名称:架构管理…

PDF转Word的方法分享与注意事项。

PDF和Word是两种常用的文档格式,它们各有优点,适用于不同的场景。然而,有时候我们需要将PDF转换为Word,以便更好地进行编辑和排版。本文将介绍几种常用的PDF转Word的方法,并分享一些注意事项。 一、PDF转Word的方法 使…

05-JVM内存分配机制深度剖析

上一篇:04-JVM对象创建深度剖析 1.对象栈上分配 我们通过JVM内存分配可以知道JAVA中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大压力&#xff…

按照xml文件和txt文件名,将对应名字的图象文件复制

按照xml文件和txt文件名,将对应名字的图象文件复制 需求分析解决方案 需求分析 就是已经标注了xml和txt文件,需要将其对应的图象文件挑选出来 解决方案 # 按照xml文件删除对应的图片 # coding: utf-8 from PIL import Image, ImageDraw, ImageFont imp…

k8s集群证书过期解决

一、k8s集群证书过期解决 问题现象 K8S集群证书过期后,会导无法创建Pod,通过kubectl get nodes也无法获取信息,甚至dashboard也无法访问。 执行命令发现报错: Unable to connect to the server: x509: certificate has expire…

使用ffmpeg截取视频片段

本文将介绍2种使用ffmpeg截取视频的方法 指定截取视频的 开始时间 和 结束时间,进行视频截取指定截取视频的 开始时间 和 截取的秒数,进行视频截取 两种截取方式的命令行如下 截取某一时间段视频 优先使用 ffmpeg -i ./input.mp4 -c:v libx264 -crf…

多维时序 | MATLAB实现GWO-GRU灰狼算法优化门控循环单元的多变量时间序列预测

多维时序 | MATLAB实现GWO-GRU灰狼算法优化门控循环单元的多变量时间序列预测 目录 多维时序 | MATLAB实现GWO-GRU灰狼算法优化门控循环单元的多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现基于GWO-GRU灰狼算法优化门控循环单元的多变量时…