2

我需要通过自动化的 python 脚本运行 OpenFOAM 命令。

我的 python 代码包含这些行

subprocess.Popen(['OF23'], shell=True)
subprocess.Popen(['for i in *; do surfaceConvert $i file_path/$i.stlb; done', shell=True)

其中 OF23 是一个 shell 命令,在别名中定义为

alias OF23='export PATH=/usr/lib64/openmpi/bin/:$PATH;export LD_LIBRARY_PATH=/usr/lib64/openmpi/lib/:$LD_LIBRARY_PATH;source /opt/OpenFOAM/OpenFOAM-2.3.x/etc/bashrc'

该脚本在终端中运行 OpenFOAM 命令,file_path 定义了转换为二进制格式的 stl 文件

但是当我运行脚本时,我得到 'OF23' 没有定义。

如何使我的脚本运行别名命令并执行下一个 OpenFOAM 文件转换命令

4

3 回答 3

6

即使您解决了alias问题,这也行不通。每个 Pythonsubprocess.Popen都在一个单独的子 shell 中运行,因此执行的效果OF23不会持续到第二个subprocess.Popen.

这是一个简短的演示:

import subprocess

subprocess.Popen('export ATEST="Hello";echo "1 $ATEST"', shell=True)
subprocess.Popen('echo "2 $ATEST"', shell=True)

输出

1 Hello
2 

因此,无论您使用别名,还是直接执行别名命令,您都需要将您的命令组合到一个subprocess.Popen调用中。

例如:

subprocess.Popen('''export PATH=/usr/lib64/openmpi/bin/:$PATH;
export LD_LIBRARY_PATH=/usr/lib64/openmpi/lib/:$LD_LIBRARY_PATH;
source /opt/OpenFOAM/OpenFOAM-2.3.x/etc/bashrc;
for i in *;
do surfaceConvert $i file_path/$i.stlb;
done''', shell=True)

我使用了三引号字符串,因此我可以插入换行符,以使 shell 命令更易于阅读。

显然,我无法在我的机器上测试那个确切的命令序列,但它应该可以工作。

于 2015-09-23T12:47:58.460 回答
4

您需要发出shopt -s expand_aliases来激活别名扩展。来自bash(1)

除非使用 shopt [...]

如果这没有帮助,请检查从您的 Python 程序执行的 shell 是否实际上是 Bash(例如通过 echoing $BASH)。

于 2015-09-23T12:37:39.930 回答
2

如果您的命令可能使用 bash-isms,那么您可以传递executable参数,否则/bin/sh使用。要扩展别名,您可以使用@Michael Jaros 的建议

#!/usr/bin/env python
import subprocess

subprocess.check_call("""
    shopt -s expand_aliases
    OF23
    for i in *; do surfaceConvert $i file_path/$i.stlb; done
"""], shell=True, executable='/bin/bash')

如果您已经有一个可以工作的 bash 脚本,那么就按原样调用它。

尽管为了使其更加健壮和可维护,您可以转换为提供最大好处的 Python 部分,例如,以下是您可以模拟 for 循环的方法:

#!/usr/bin/env python
import subprocess

for entry in os.listdir():
    subprocess.check_call(['/path/to/surfaceConvert', entry, 
                           'file_path/{entry}.stlb'.format(entry)])

它允许文件名包含 shell 元字符,例如空格。

要为子进程配置环境,您可以使用 Popen 的env参数,例如env=dict(os.environ, ENVVAR='value').

可以在 Python中模拟sourcebash 命令,但您可能应该将依赖它的部分留在 bash-script 中。

于 2015-09-23T17:54:13.027 回答