首页 > 编程知识 正文

常用python编程软件,编程

时间:2023-05-04 02:38:38 阅读:160778 作者:4560

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

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

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

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

构建程序代码和数据

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

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

某些代码段可以同时执行,因此原则上允许并行执行

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

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

要使用子流程,需要重新考虑程序从线性到并行的执行方式。 这类似于将公司的工作视角从普通员工转变为经理——。 必须关注谁在做什么,某一步骤需要多长时间,以及中间结果之间的依赖关系。

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

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

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

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

是否允许并行化数据? 如果不允许,数据组织如何调整?

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

需要调整硬件吗?

硬件或算法中存在瓶颈吗? 如何避免或最小化这些因素的影响?

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

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

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

执行与Python并行的函数

Python有四种可能的处理方法。 您可以首先使用多进程模块并行执行功能。 第二,进程的替代方法是线程。 从技术上来说,这些是轻量级的过程,不在本文的范围之内。 如果想知道更详细的内容,请看看Python的线程模块。 第三,操作系统模块的system (可以使用方法或subprocess模块提供的方法调用外接程序来收集结果。

mulTIprocessing模块涵盖了一组处理并行执行例程的方法。 这包括进程、代理池、队列和管道。

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

Pool.map ) )方法需要三个参数:在数据集的每个元素上调用的函数、数据集本身和chunksize。 清单1使用square函数计算给定整数值的平方。 此外,chunksize不是必需的。 如果未明确设置,则缺省chunksize为1。

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

清单1 :并行执行函数

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

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

使用队列执行多个函数

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

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

清单2.1 :使用的模块

然后定义工作器函数[清单2.2。 此函数实际上表示代理,需要三个参数。 进程名称指明是哪个进程,tasks和results都指向相应的队列。

在功函数中是while循环。 tasks和results都是在主程序中定义的队列。 tasks.get ()来自关键位置

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

清单2.2:worker函数

下一步是主循环(参见清单2.3)。首先,定义了进程间通信(IPC)的经理。接下来,添加两个队列,一个保留任务,另一个用于结果。

清单2.3:IPC和队列

完成此设置后,我们定义一个具有四个工作进程(代理)的进程池。我们使用类multiprocessing.Pool(),并创建一个它的实例。 接下来,我们定义一个空的进程列表(见清单2.4)。

清单2.4:定义一个进程池

作为以下步骤,我们启动了四个工作进程(代理)。 为了简单起见,它们被命名为“P0”到“P3”。使用multiprocessing.Pool()完成创建四个工作进程。这将它们中的每一个连接到worker功能以及任务和结果队列。 最后,我们在进程列表的末尾添加新初始化的进程,并使用new_process.start()启动新进程(参见清单2.5)。

清单2.5:准备worker进程

我们的工作进程正在等待工作。我们定义一个任务列表,在我们的例子中是任意选择的整数。这些值将使用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()调用。子过程的想法是简化产卵过程,通过管道和信号与他们进行通信,并收集他们生成的输出包括错误消息。

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

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

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

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

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

要抑制输出到stdout,并捕获输出和返回值进行进一步的评估,subprocess.run()的调用必须稍作修改。没有进一步修改,subprocess.run()将执行的命令的输出发送到stdout,这是底层Python进程的输出通道。 要获取输出,我们必须更改此值,并将输出通道设置为预定义值subprocess.PIPE。清单5显示了如何做到这一点。

清单5:抓取管道中的输出

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

结论

由于现在的硬件已经很厉害了,因此也给并行处理提供了绝佳的机会。Python也使得用户即使在非常复杂的级别,也可以访问这些方法。正如在multiprocessing和subprocess模块之前看到的那样,可以让你很轻松的对该主题有很深入的了解。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。