【问题标题】:Python - using os.subprocess to call a shell script with nested commands [closed]Python - 使用 os.subprocess 调用带有嵌套命令的 shell 脚本 [关闭]
【发布时间】:2018-02-26 15:42:01
【问题描述】:

我正在使用 python 运行顶级遗传算法,以使用 OpenFOAM 优化 3D 飞机机翼几何形状以获得空气动力学性能。我正在运行 Ubuntu 16.04、Python 3.6 和 OpenFOAM 5。我编写了几个位于 OpenFOAM 案例目录(包含几何 STL 文件、流体动力学参数和网格的目录)中的 shell 脚本。这些脚本执行重复的文件管理命令和 OpenFOAM 并行过程分解程序,以及生成 3D 网格和运行模拟的命令。 python 脚本应该完全位于不同的目录中,因为这些案例文件夹中的数百个(如果不是数千个)将作为遗传算法的后代生成。问题是使用 os.subprocess 调用这些 shell 脚本似乎会为脚本中的每个命令生成并终止一个 shell。例如,如果我的代码是(简要版):

#!/bin/bash
rm constant/polyMesh/*
rm constant/triSurface/*.eMesh
rm -rf 0.*
find -type d -name '*e-0*' -exec rm -r {} +
decomposePar (OpenFOAM utility)

我将所说的脚本称为:

subprocess.Popen(['./shellScript'],cwd=r'./pathToDirectory')

我最终得到了错误:

./shellScript: line #: decomposePar no such file or directory

如果 shell 试图在 case 目录以外的目录中执行 decomposePar,我可以看到这种情况发生的唯一方法(它应该顺利运行)。对于案例管理命令,似乎只有第一个命令有效。我已经抓取了堆栈溢出来解决这个问题,但我不确定我是否找到了一个。我尝试使用os.chdir('casePath') 设置python 脚本的工作目录,设置cwd='casePath',以及其他几个我不太明白的subprocess 参数!

我知道我可以将每个 shell 命令转录成 Python,但我发现由于 shell 命令的数量以及将来可能更改这些 shell 脚本,这将非常乏味。我希望我的方法是模块化的并且足够健壮,可以只运行几个我可以根据需要修改的脚本。此外,最终该程序将部署到超级计算机上。并行处理将发生在 OpenFOAM 中的 C++ 级别,而不是 python,所以这不是我关心的问题之一。有什么办法可以做到这一点,我是否错过了一些非常明显的东西?请耐心等待,因为计算机科学不是我的强项,我是一名航空工程师。谢谢!

【问题讨论】:

  • 不知道为什么你需要r''和subprocess.Popen你不需要./它应该是第一个参数的列表是可执行文件Popen(['/bin/sh', '-c', args[0], args[1], ...])
  • 你能提供一些真实的代码而不是伪代码吗?
  • 查看docs.python.org/3.6/library/subprocess.html#popen-constructor 了解更多信息。你的情况你应该需要subprocess.Popen(['/bin/sh', 'shellScript'])
  • @jackotonye 我已经更新了我的帖子
  • decomposePar 在哪里,您应该使用os.getcwd() os.chdir() wd = os.getcwd() os.chdir("/") subprocess.Popen("ls") os.chdir(wd)

标签: python shell subprocess openfoam


【解决方案1】:

TL;DR:在 shell 脚本开始时从 OpenFOAM 安装中获取bashrc

在对 OP 进行一些挖掘之后,问题最初是包含 decomposePar 的目录不在 PATH 环境变量中。

除非你的 PATH 中有.(这很危险,不要这样做),将当前目录更改为目录不会对找到decomposePar 产生任何影响。在 shell 脚本中添加到 decomposePar 的完整路径允许运行 decomposePar

例子:

#!/bin/bash
rm constant/polyMesh/*
rm constant/triSurface/*.eMesh
rm -rf 0.*
find -type d -name '*e-0*' -exec rm -r {} +
/full/path/to/decomposePar

但是,在运行时,它无法加载所需的共享库,因为 OpenFOAM 共享库目录不在 LD_LIBRARY_PATH 环境变量中。为了解决这个问题,OpenFOAM bashrc 文件位于脚本的开头。

例子:

#!/bin/bash
source /path/to/bashrc
rm constant/polyMesh/*
...

对该文件进行排序可以正确设置PATHLD_LIBRARY_PATH 环境变量。

【讨论】:

  • 我尝试添加./ 并得到完全相同的结果。此外,在案例目录中运行 decomposePar 在命令行中也可以正常工作。你是说如果我将它添加到路径环境变量中,它将能够在案例目录中执行?
  • 要排除与路径相关的问题,您可以尝试在脚本中使用完整路径,看看是否可行,然后向后工作。
  • 在 Popen 命令中使用完整路径会产生相同的结果。再加上多行tput: No value for $TERM and no -T specified
  • @denbjornen505 抱歉,这是一个问题,还是您说的是您目前正在做的事情?如果这是一个问题,不,我的意思是在 shell 脚本本身。例如,如果您可以将示例中的最后一行更改为 /full/path/to/decomposePar
  • 在脚本中使用完整路径时:/opt/openfoam5/platforms/linux64GccDPInt32Opt/bin/decomposePar 现在正在执行 decomposePar。但是 decomposePar 执行的一些实用程序现在抱怨(同样的错误)
猜你喜欢
  • 1970-01-01
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-10
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
  • 2017-08-15
相关资源
最近更新 更多