用Python编程,Python的编程软件

  用Python编程,Python的编程软件

  当舒适的音乐启动机器——程序时,它只是在自己的“泡泡”中工作。这个气泡的作用是将所有同时工作的程序分开。这个“气泡”,也称为进程,包含了管理程序调用所需的一切。

  例如,进程环境包括进程使用的内存页面、进程打开的文件的处理、用户和组的权限以及带有指定参数的整个命令行调用。

  这些信息存储在UNIX/Linux系统的进程文件系统中,这是一个可以从/proc目录访问的虚拟文件系统。条目根据进程ID进行排序,进程ID是每个进程的唯一标识符。1该示例显示了进程ID为#177的任何进程。

  示例1:可用于流程的信息

  构建程序代码和数据

  越复杂,越有助于把它分成小模块。不仅是源代码,机器上运行的代码也适用这个规则。这一规则的典型例子是使用子进程的并行执行。背后的想法是:

  一个进程包含可以单独执行的代码段。

  有些代码段可以同时执行,所以原则上允许并行执行。

  利用现代处理器和操作系统的特性,包括处理器的所有内核,可以缩短程序的总执行时间。

  降低程序/代码的复杂性,将业务外包给专业代理。

  要使用子进程,就要从线性到并行重新考虑程序的执行方式。这类似于把公司的工作视角从一个普通员工变成了一个管理者3354。我们必须注意谁在做什么,某个步骤需要多长时间,以及中间结果之间的依赖关系。

  这有助于将代码分成更小的部分。这些小部分可以由专门负责此任务的代理来执行。如果你还不知道,请考虑数据集的结构原理。这也是同样的道理,单个代理就能有效处理。但这也引发了一些问题:

  为什么要并行化代码?在具体的案例中,在努力中付诸实践,思考这个问题有意义吗?

  你打算只运行这个程序一次吗?还是定期在类似的数据集上运行?

  你能把算法分成几个独立的执行步骤吗?

  允许数据并行化?如果没有,如何调整数据组织?

  计算的中间结果是相互依赖的吗?

  需要调整硬件吗?

  硬件算法是否存在瓶颈?如何避免或尽量减少这些因素的影响?

  并行化的其他副作用是什么?

  可能的用例是在后台运行并等待启动的主进程和守护进程(主/从)。它也可能是启动按需工作流的主要流程之一。实际上,主进程是feed进程,它控制两个以上feed的数据部分的代理,并在给定的部分中进行计算。

  请注意,由于操作系统所需的子进程开销,并行处理是昂贵且耗时的。与线性执行多个任务相比,在并行的情况下,根据用例,每个子流程可以节省25%到30%的时间。例如,如果连续执行两个需要5秒的任务,总共需要10秒,而对于并行化,多核计算机平均需要8秒。这八秒中的三秒可能会在你的脑海中消失,限制你的速度。

  执行与Python并行的函数

  Python有四种可能的处理方法。您可以首先使用多进程模块并行执行功能。其次,进程的替代品是线程。从技术上讲,这些都是轻量级的过程,超出了本文的范围。如果你想知道更多的细节,请看看Python的线程模块。三、操作系统模块的系统(可以使用方法或者子进程模块提供的方法调用外接程序收集结果。

  多重处理模块包括一组处理并行执行程序的方法。这包括进程、代理池、队列和管道。

  清单1使用五个代理池,同时处理三个值的块。出于演示目的,代理的数量和chunksize的值是可选的。这些值根据处理器内核的数量进行调整。

  Pool.map))方法需要三个参数:对数据集的每个元素调用的函数、数据集本身和chunksize。清单1使用square函数计算给定整数值的平方。此外,chunksize不是必需的。如果没有显式设置,默认chunksize为1。

  请注意,虽然不能保证代理的执行顺序,但结果集的顺序是正确的。根据原始数据集中的元素顺序包含平方值。

  清单1:并行执行函数

  执行此代码将生成以下输出:

  注意:使用Python 3作为这些例子。

  使用队列执行多个功能。

  队列作为一种数据结构,是非常常见的,并且以各种方式存在。FIFO或LIFO/堆栈和优先级(优先级队列)组织。结构可以实现为具有固定数量条目的数组,也可以实现为包含变量的单个元素的列表。

  清单2.1-2.7使用FIFO队列。它已经被实现为多处理模块中相应类提供的列表。此外,将加载时间模块并用于模拟工作负载。

  清单2.1:使用的模块

  然后定义工人函数[清单2.2。这个函数实际上代表一个代理,需要三个参数。进程名表示是哪个进程,任务和结果都指向对应的队列。

  在功函数中,这是一个while循环。任务和结果是在主程序中定义的队列。Tasks.get()来自一个关键位置

  返回管理器任务队列中的当前任务。小于0的任务值退出while循环,返回值为-1。任何其他任务值将执行计算(平方)并返回该值。返回给主程序的值被实现为result.put()。这将在结果队列的末尾添加计算值。

  清单2.2:工人函数

  下一步是主循环(参见清单2.3)。首先,对IPC的管理者进行了界定。接下来,添加两个队列,一个用于保留的任务,另一个用于结果。

  清单2.3:IPC和队列

  设置完成后,我们定义了一个包含四个工作进程(代理)的进程池。我们使用类多重处理。Pool()并创建它的一个实例。接下来,我们定义一个空的进程列表(参见清单2.4)。

  清单2.4:定义进程池

  按照下面的步骤,我们启动了四个工作流程(代理)。为简单起见,它们被命名为“P0”到“P3”。使用多重处理。Pool()来完成四个工作进程的创建。将它们分别连接到工作函数以及任务和结果队列。最后,我们在进程列表的末尾添加新初始化的进程,并用new_process.start()启动新进程(参见清单2.5)。

  清单2.5:准备工作进程

  我们的工作流程是等待工作。我们定义了一个任务列表,在我们的例子中,它是一个任意选择的整数。这些值将使用tasks.put()添加到任务列表中。每个工作进程等待一个任务,并从任务列表中选择下一个可用的任务。这是由队列本身处理的(参见清单2.6)。

  清单2.6:准备任务队列

  过一会儿,我们希望我们的代理会结束。每个工作进程对值为-1的任务做出反应。它将该值解释为终止信号,然后终止。这就是为什么我们在任务队列中放置尽可能多的-1,因为我们有正在运行的进程。崩溃前,被终止的进程将在结果队列中放入-1。这意味着这是代理正在终止的主循环的确认信号。

  在主循环中,我们从这个队列中读取并计数-1。一旦我们计算出流程的终止确认数,主循环将退出。否则,我们从队列中输出计算结果。

  清单2.7:结果的终止和输出

  示例2显示了Python程序的输出。多次运行该程序,您可能会注意到,对于从队列中选择任务的进程本身,工作进程的启动顺序是不可预测的。然而,一旦结果队列元素的顺序与任务队列元素的顺序匹配。

  示例2

  注意:如前所述,由于不可预测的执行顺序,您的输出可能与上面显示的输出不一致。

  使用os.system()方法。

  system()方法是os模块的一部分,它允许外部命令行程序在独立于Python程序的进程中执行。system()方法是一个阻塞调用。你要等到电话打完了再回来。作为UNIX/Linux爱好者,您知道可以在后台运行命令,并将计算结果写入重定向到这样一个文件的输出流中(参见示例3):

  示例3:带有输出重定向的命令

  在Python程序中,您只需将此调用封装如下:

  清单3:使用os模块的简单系统调用

  这个系统调用创建了一个与当前Python程序并行运行的进程。得到结果可能有点棘手,因为这个调用可能会在Python程序结束后终止——你永远不知道。

  使用这种方法比我描述的前一种方法要昂贵得多。首先,开销要高得多(进程切换),其次,它将数据写入物理内存,比如需要更长时间的磁盘。虽然这是一个更好的选择,你的内存是有限的(像RAM),但是你可以把大量的输出数据写到固态硬盘。

  使用子流程模块

  此模块旨在替换os.system()和os.spawn()调用。subprocess的思想是简化生成过程,通过管道和信号与它们通信,并收集它们生成的输出,包括错误消息。

  从Python 3.5开始,子流程包含方法subprocess.run()来启动外部命令,该命令是底层子流程的包装器。Popen()类。例如,我们启动UNIX/Linux命令df -h来找出机器的/home分区上还有多少磁盘空间。在Python程序中,您可以执行如下所示的调用(清单4)。

  清单4:运行外部命令的基本示例

  这是一个基本的调用,非常类似于在终端中执行的命令df -h/home。请注意,参数被分成列表,而不是单独的字符串。输出将类似于示例4。与该模块的官方Python文档相比,它除了将调用的返回值输出到stdout之外,还将调用结果输出到stdout。

  示例4显示了我们调用的输出。输出的最后一行显示了命令的成功执行。调用subprocess.run()会返回CompletedProcess类的一个实例,该类有两个名为args(命令行参数)和returncode(命令的返回值)的属性。

  示例4:运行清单4中的Python脚本

  要禁止输出到stdout并捕获输出和返回值以供进一步评估,必须稍微修改对subprocess.run()的调用。无需进一步修改,subprocess.run()将执行命令的输出发送到stdout,这是底层Python流程的输出通道。要获得输出,我们必须更改这个值,并将输出通道设置为预定义的值子流程。管道清单5展示了如何做到这一点。

  清单5:从管道中获取输出

  如前所述,subprocess.run()返回CompletedProcess类的一个实例。在清单5中,这个实例是一个名为output的变量。该命令的返回代码保存在属性output.returncode中,打印到stdout的输出可以在属性output.stdout中找到。请注意,这不包括处理错误消息,因为我们没有更改输出通道。

  结论

  现在硬件很强大,所以也为并行处理提供了绝佳的机会。Python也使用户能够访问这些方法,即使是在非常复杂的层次上。正如你在多进程和子进程模块之前所看到的,你可以很容易地对主题有深入的理解。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: