bash 从 python 脚本调用别名命令

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32739635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 13:36:40  来源:igfitidea点击:

Calling alias Command from python script

pythonbashshellsubprocessopenfoam

提问by Balaji Spades

I need to run an OpenFOAM command by automatized python script.

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

My python code contains the lines

我的 python 代码包含这些行

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

where OF23 is a shell command is defined in alias as

其中 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'

This script runs the OpenFOAM command in terminal and the file_path defines the stl files which are converted to binary format

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

But when I run the script, I am getting 'OF23' is not defined.

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

How do I make my script to run the alias command and also perform the next OpenFOAM file conversion command

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

回答by PM 2Ring

That's not going to work, even once you've resolved the aliasproblem. Each Python subprocess.Popenis run in a separate subshell, so the effects of executing OF23won't persist to the second subprocess.Popen.

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

Here's a brief demo:

这是一个简短的演示:

import subprocess

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

output

输出

1 Hello
2 

So whether you use the alias, or just execute the aliased commands directly, you'll need to combine your commands into one subprocess.Popencall.

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

Eg:

例如:

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)

I've used a triple-quoted string so I can insert linebreaks, to make the shell commands easier to read.

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

Obviously, I can't test that exact command sequence on my machine, but it shouldwork.

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

回答by Michael Jaros

You need to issue shopt -s expand_aliasesto activate alias expansion. From bash(1):

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

Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt [...]

当 shell 不是交互式时,别名不会被展开,除非使用 shopt [...] 设置 expand_aliases shell 选项

If that does not help, check if the shell executed from your Python program is actually Bash (e.g. by echoing $BASH).

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

回答by jfs

If your command may use bash-isms then you could pass executableparameter otherwise /bin/shis used. To expand aliases, you could use @Michael Jaros' suggestion:

如果您的命令可能使用 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')

If you already have a working bash-script then just call it as is.

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

Though to make it more robust and maintainable, you could convert to Python parts that provide the most benefit e.g., here's how you could emulate the for-loop:

虽然为了使其更健壮和可维护,您可以转换为提供最大好处的 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)])

It allows filenames to contain shell meta-characters such as spaces.

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

To configure the environment for a child process, you could use Popen's envparameter e.g., env=dict(os.environ, ENVVAR='value').

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

It is possible to emulate sourcebash command in Pythonbut you should probably leave the parts that depend on it in bash-script.

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