加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

如何将父变量传递给python中的子进程?

发布时间:2020-12-20 12:32:07 所属栏目:Python 来源:网络整理
导读:我试图让一个父 python脚本将变量发送到子脚本,以帮助我加速和自动化视频分析. 我现在使用subprocess.Popen()调用来启动子脚本的6个实例,但是找不到将父进程中已经调用的变量和模块传递给子进程的方法.例如,父文件将具有: import sysimport subprocessparen
我试图让一个父 python脚本将变量发送到子脚本,以帮助我加速和自动化视频分析.

我现在使用subprocess.Popen()调用来启动子脚本的6个实例,但是找不到将父进程中已经调用的变量和模块传递给子进程的方法.例如,父文件将具有:

import sys
import subprocess
parent_dir = os.path.realpath(sys.argv[0])
subprocess.Popen(sys.executable,'analysis.py')

但然后导入sys;导入子流程;必须在“analysis.py”中再次调用parent_dir.有没有办法将它们传给孩子?

简而言之,我想要实现的是:我有一个包含几百个视频文件的文件夹.我希望父python脚本列出视频文件并启动分析脚本的6个并行实例,每个实例分析一个视频文件.如果没有更多要分析的文件,则父文件将停止.

解决方法

这里的简单答案是:不要使用subprocess.Popen,使用 multiprocessing.Process.或者,更好的是,multiprocessing.Pool或 concurrent.futures.ProcessPoolExecutor.

使用子进程,程序的Python解释器根本不了解子进程;据它所知,子进程正在运行Doom.所以没有办法直接与它共享信息.*但是通过多处理,Python控件启动子流程并设置所有内容,以便您可以尽可能方便地共享数据.

不幸的是,“尽可能方便”仍然不像在一个过程中那样方便100%.但你能做的通常是足够好的.阅读Exchanging objects between processes部分和以下几节;希望其中一个机制正是您所需要的.

但是,正如我在顶部隐含的那样,在大多数情况下,您可以通过使用池来使其更简单.不要考虑“运行6个进程并与它们共享数据”,而是将其视为“在6个进程池上运行一堆任务”.任务基本上只是一个函数 – 它接受参数,并返回一个值.如果您要并行化的工作适合该模型 – 听起来就像您的工作一样 – 生活就像生活一样简单.例如:

import multiprocessing
import os
import sys

import analysis

parent_dir = os.path.realpath(sys.argv[0])

paths = [os.path.join(folderpath,file) 
         for file in os.listdir(folderpath)]

with multiprocessing.Pool(processes=6) as pool:
    results = pool.map(analysis.analyze,paths)

如果您使用的是Python 3.2或更早版本(包括2.7),则不能在with语句中使用Pool.我相信你想要这个:**

pool = multiprocessing.Pool(processes=6)
try:
    results = pool.map(analysis.analyze,paths)
finally:
    pool.close()
    pool.join()

这将启动6个进程,***然后告诉第一个进行分析.分析(路径[0]),第二个做分析.分析(路径[1])等.一旦任何进程完成后,游泳池将为其提供下一个工作路径.当它们全部完成后,您将获得所有结果的列表.****

当然,这意味着生活在analysis.py中的顶级代码必须移动到函数def analyze(path)中:所以你可以调用它.或者,如果您确实要保存该导入行,则可以将该函数移动到主脚本中,而不是单独的文件中.

*你仍然可以间接地共享信息,例如,将它编组成一些交换格式,如JSON,并通过stdin / stdout管道,文件,共享内存段,套接字等传递它,但是多处理有效地包含了这些信息.你要让它变得更容易.

**关闭池有不同的方法,你也可以选择是否立即加入它,所以你真的应该在某些时候阅读细节.但是当你所做的只是调用pool.map时,它确实没关系;保证游泳池关闭并准备好在地图呼叫返回时立即加入.

***我不确定你为什么要6;大多数机器有4个,8个或16个核心,而不是6个;为什么不全部使用它们?最好的做法通常是完全省略进程= 6并让多处理器向你的操作系统询问使用多少内核,这意味着它仍然可以在你的新机器上全速运行,内核数量是你的两倍.明年会买.

****这有点过于简单;通常,池会为第一个进程提供一批文件,而不是一次一个,以节省一些开销,如果需要优化或更仔细地对它们进行优化,则可以手动控制批处理.但通常你不在乎,这种过度简化是好的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读