【问题标题】:Calling alias Command from python script从 python 脚本调用别名命令
【发布时间】:2015-12-20 18:35:46
【问题描述】:

我需要通过自动化 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 文件转换命令

【问题讨论】:

    标签: python bash shell subprocess openfoam


    【解决方案1】:

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

    #!/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')

    emulate source bash command in Python 是可能的,但您可能应该将依赖它的部分留在 bash-script 中。

    【讨论】:

      【解决方案2】:

      即使您解决了alias 问题,这也行不通。每个 Python subprocess.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 命令更易于阅读。

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

      【讨论】:

      • 感谢您的想法。它有效,我就像你建议的那样使用p=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 '+path+'/*;do surfaceConvert $i $i.stlb;done', shell=True) p.wait()
      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多