从 python 评估 "Shell command line with shell variables" 或评估 python 字符串作为 shell 命令行
Evaluate "Shell command line with shell variables" from python OR evaluate python string as shell command line
上下文
我正在研究模拟集群。
为了尽可能灵活(使用不同的模拟软件),我们创建了一个 python 文件来解析定义环境变量的配置文件,以及启动模拟的命令行。此命令通过 SLURM sbatch 命令启动 (shell $COMMAND)
问题
从python开始,所有环境变量都已注册读取配置文件
我对使用其他环境变量的变量 COMMAND 有疑问(显示为 shell 变量)
例如
COMMAND = "fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE"
os.environ['COMMAND']=COMMAND
NUMPROCS = "32"
os.environ['NUMPROCS']=NUMPROCS
[...]
exe = Popen(['sbatch','template_document.sbatch'], stdout=PIPE, stderr=PIPE)
sbatch将COMMAND分发到所有模拟节点,因为COMMAND是命令行
COMMAND 调用其他已保存的环境。变量。 Shell 将其严格解释为文本...这使得命令行失败。它严格作为一个字符串使用 $ not variable 例如:
'fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE'
我正在寻找的解决方案
我正在寻找一个简单的解决方案
解决方案 1:1 到 3 python 命令行将 COMMAND 评估为 shell 命令以回显
解决方案 2:Shell 命令将 "string" $COMMAND 中的变量作为变量求值
最后,从 sbatch 中启动的命令应该是
fluent -3ddp -n32 -hosts=./hosts -file /path/to/JOBFILE
您有几个选择:
部分或不支持bash的变量替换,例如实施一些 python 功能以重现 bash 的 $VARIABLE
语法。
重现配置文件中支持的所有 bash 的变量替换功能($VARIABLE
、${VARIABLE}
、${VARIABLE/x/y}
、$(cmd)
- 随便。
让 bash 完成繁重的工作,以牺牲性能和可能的安全性为代价,这取决于您对配置文件内容的信任程度。
我将在这里展示第三个,因为它是最有弹性的(同样,尽管存在安全问题)。假设您有这个配置文件,config.py
:
REGULAR = "some-text"
EQUALS = "hello = goodbye" # trap #1: search of '='
SUBST = "decorated $REGULAR"
FANCY = "xoxo${REGULAR}xoxo"
CMDOUT = "$(date)"
BASH_A = "trap" # trap #2: avoid matching variables like BASH_ARGV
QUOTES = "'\"" # trap #3: quoting
然后你的python程序可以运行下面的咒语:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && env | grep -f <(cut -d= -f1 config.py | grep -E -o "\w+" | sed "s/.*/^&=/")'
这将产生以下输出:
SUBST=decorated some-text
CMDOUT=Thu Nov 28 12:18:50 PST 2019
REGULAR=some-text
QUOTES='"
FANCY=xoxosome-textxoxo
EQUALS=hello = goodbye
BASH_A=trap
然后您可以使用 python 阅读,但请注意,引号现已消失,因此您必须考虑到这一点。
咒语解释:
bash -c 'source ...instructions... && env | grep ...expressions...'
告诉 bash 阅读和解释指令,然后 grep 表达式的环境。我们要把配置文件变成修改bash环境的指令。
如果您尝试使用 set
而不是 env
,输出将在引用方面不一致。使用 env
避免陷阱 #3.
说明:我们将为表单创建说明:
export FANCY="xoxo${REGULAR}xoxo"
以便 bash 可以解释它们并且 env
可以阅读它们。
sed "s/^/export /" config.py
为变量添加前缀 export
。
sed "s/[[:space:]]*=[[:space:]]*/=/"
将赋值格式转换为 bash 可以用 source
读取的语法。使用 s/x/y/
而不是 s/x/y/g
可以避免陷阱 #1.
source <(...command...)
导致 bash 将命令的输出作为一个文件和 运行 它的行逐行处理。
当然,避免这种复杂性的一种方法是让文件以 bash 语法开头。如果是这样,我们将使用 source config.sh
而不是 source <(...command...)
.
表达式:我们想为^FANCY=
.
这样的模式grep env
的输出
cut -d= -f1 config.py | grep -E -o "\w+"
查找 config.py
. 中的变量名
sed "s/.*/^&=/"
将 FANCY
等变量名转换为 ^FANCY=
等 grep 搜索表达式。这是为了避免陷阱#2。
grep -f <(...command...)
获取 grep
以将命令的输出视为每行包含一个搜索表达式的文件,在本例中为 ^FANCY=
、^CMDOUT=
等
编辑
由于您实际上只想将此环境传递给另一个 bash 命令,而不是在 python 中使用它,您实际上可以只使用 python 运行 这个:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && $COMMAND'
(假设在配置文件中指定了COMMAND
)。
看来我对这个问题的解释还不够好,但是你的第三个解决方案似乎符合我的期望...虽然到目前为止我还没有设法适应它
根据你的第三个解决方案BASH,我会更直接:
假设我在 运行 python 之后得到了关注,并且无法修改
EXPORT COMMAND='fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE'
EXPORT JOBFILE='/path/to/jobfile'
EXPORT NUMPROCS='32'
EXPORT WHATSOEVER='SPECIFIC VARIABLE TO SIMULATION SOFTWARE'
我希望使用 $COMMAND / $JOBFILE /$NUMPROCS
从 slurm 批处理文件 (bash) 执行以下命令
fluent -3ddp -n32-hosts=./hosts -file /path/to/jobfile
请注意:我在 python 中有备份解决方案 - 我设法用它的值替换 $VARIABLE - 基于假设 $VARIABLE 不是由另一个 $variable 组成...使用正则表达式替换.. . 在我看来简单的请求看起来有那么多行
上下文
我正在研究模拟集群。 为了尽可能灵活(使用不同的模拟软件),我们创建了一个 python 文件来解析定义环境变量的配置文件,以及启动模拟的命令行。此命令通过 SLURM sbatch 命令启动 (shell $COMMAND)
问题
从python开始,所有环境变量都已注册读取配置文件 我对使用其他环境变量的变量 COMMAND 有疑问(显示为 shell 变量)
例如
COMMAND = "fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE"
os.environ['COMMAND']=COMMAND
NUMPROCS = "32"
os.environ['NUMPROCS']=NUMPROCS
[...]
exe = Popen(['sbatch','template_document.sbatch'], stdout=PIPE, stderr=PIPE)
sbatch将COMMAND分发到所有模拟节点,因为COMMAND是命令行
COMMAND 调用其他已保存的环境。变量。 Shell 将其严格解释为文本...这使得命令行失败。它严格作为一个字符串使用 $ not variable 例如:
'fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE'
我正在寻找的解决方案
我正在寻找一个简单的解决方案 解决方案 1:1 到 3 python 命令行将 COMMAND 评估为 shell 命令以回显 解决方案 2:Shell 命令将 "string" $COMMAND 中的变量作为变量求值 最后,从 sbatch 中启动的命令应该是
fluent -3ddp -n32 -hosts=./hosts -file /path/to/JOBFILE
您有几个选择:
部分或不支持bash的变量替换,例如实施一些 python 功能以重现 bash 的
$VARIABLE
语法。重现配置文件中支持的所有 bash 的变量替换功能(
$VARIABLE
、${VARIABLE}
、${VARIABLE/x/y}
、$(cmd)
- 随便。让 bash 完成繁重的工作,以牺牲性能和可能的安全性为代价,这取决于您对配置文件内容的信任程度。
我将在这里展示第三个,因为它是最有弹性的(同样,尽管存在安全问题)。假设您有这个配置文件,config.py
:
REGULAR = "some-text"
EQUALS = "hello = goodbye" # trap #1: search of '='
SUBST = "decorated $REGULAR"
FANCY = "xoxo${REGULAR}xoxo"
CMDOUT = "$(date)"
BASH_A = "trap" # trap #2: avoid matching variables like BASH_ARGV
QUOTES = "'\"" # trap #3: quoting
然后你的python程序可以运行下面的咒语:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && env | grep -f <(cut -d= -f1 config.py | grep -E -o "\w+" | sed "s/.*/^&=/")'
这将产生以下输出:
SUBST=decorated some-text
CMDOUT=Thu Nov 28 12:18:50 PST 2019
REGULAR=some-text
QUOTES='"
FANCY=xoxosome-textxoxo
EQUALS=hello = goodbye
BASH_A=trap
然后您可以使用 python 阅读,但请注意,引号现已消失,因此您必须考虑到这一点。
咒语解释:
bash -c 'source ...instructions... && env | grep ...expressions...'
告诉 bash 阅读和解释指令,然后 grep 表达式的环境。我们要把配置文件变成修改bash环境的指令。
如果您尝试使用 set
而不是 env
,输出将在引用方面不一致。使用 env
避免陷阱 #3.
说明:我们将为表单创建说明:
export FANCY="xoxo${REGULAR}xoxo"
以便 bash 可以解释它们并且 env
可以阅读它们。
sed "s/^/export /" config.py
为变量添加前缀export
。sed "s/[[:space:]]*=[[:space:]]*/=/"
将赋值格式转换为 bash 可以用source
读取的语法。使用s/x/y/
而不是s/x/y/g
可以避免陷阱 #1.source <(...command...)
导致 bash 将命令的输出作为一个文件和 运行 它的行逐行处理。
当然,避免这种复杂性的一种方法是让文件以 bash 语法开头。如果是这样,我们将使用 source config.sh
而不是 source <(...command...)
.
表达式:我们想为^FANCY=
.
env
的输出
cut -d= -f1 config.py | grep -E -o "\w+"
查找config.py
. 中的变量名
sed "s/.*/^&=/"
将FANCY
等变量名转换为^FANCY=
等 grep 搜索表达式。这是为了避免陷阱#2。grep -f <(...command...)
获取grep
以将命令的输出视为每行包含一个搜索表达式的文件,在本例中为^FANCY=
、^CMDOUT=
等
编辑
由于您实际上只想将此环境传递给另一个 bash 命令,而不是在 python 中使用它,您实际上可以只使用 python 运行 这个:
bash -c 'source <(sed "s/^/export /" config.py | sed "s/[[:space:]]*=[[:space:]]*/=/") && $COMMAND'
(假设在配置文件中指定了COMMAND
)。
看来我对这个问题的解释还不够好,但是你的第三个解决方案似乎符合我的期望...虽然到目前为止我还没有设法适应它
根据你的第三个解决方案BASH,我会更直接: 假设我在 运行 python 之后得到了关注,并且无法修改
EXPORT COMMAND='fluent -3ddp -n$NUMPROCS -hosts=./hosts -file $JOBFILE'
EXPORT JOBFILE='/path/to/jobfile'
EXPORT NUMPROCS='32'
EXPORT WHATSOEVER='SPECIFIC VARIABLE TO SIMULATION SOFTWARE'
我希望使用 $COMMAND / $JOBFILE /$NUMPROCS
从 slurm 批处理文件 (bash) 执行以下命令fluent -3ddp -n32-hosts=./hosts -file /path/to/jobfile
请注意:我在 python 中有备份解决方案 - 我设法用它的值替换 $VARIABLE - 基于假设 $VARIABLE 不是由另一个 $variable 组成...使用正则表达式替换.. . 在我看来简单的请求看起来有那么多行