Вызов команды псевдонима из скрипта python

Мне нужно запустить команду OpenFOAM с помощью автоматизированного скрипта Python.

Мой код Python содержит строки

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

где OF23 — это команда оболочки, определенная в псевдониме как

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


person Balaji Spades    schedule 23.09.2015    source источник


Ответы (3)


Это не сработает, даже если вы решите проблему alias. Каждый Python subprocess.Popen запускается в отдельной подоболочке, поэтому эффекты выполнения 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.

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)

Я использовал строку в тройных кавычках, чтобы можно было вставлять разрывы строк, чтобы облегчить чтение команд оболочки.

Очевидно, я не могу протестировать именно эту последовательность команд на своем компьютере, но она должна работать.

person PM 2Ring    schedule 23.09.2015
comment
Спасибо за вашу идею. Это сработало, я использовал так, как вы предложили 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() - person Balaji Spades; 23.09.2015

Вам нужно ввести shopt -s expand_aliases, чтобы активировать расширение псевдонима. От bash(1):

Псевдонимы не расширяются, когда оболочка не интерактивна, если только опция оболочки expand_aliases не установлена ​​с помощью [...]

Если это не помогает, проверьте, действительно ли оболочка, выполняемая из вашей программы Python, является Bash (например, повторив $BASH).

person Michael Jaros    schedule 23.09.2015

Если ваша команда может использовать башизмы, вы можете передать параметр 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)])

Это позволяет именам файлов содержать метасимволы оболочки, такие как пробелы.

Чтобы настроить среду для дочернего процесса, вы можете использовать параметр env Popen, например, env=dict(os.environ, ENVVAR='value').

Можно эмулировать команду source bash в Python, но вам, вероятно, следует оставить части, которые зависят от нее, в сценарии bash.

person jfs    schedule 23.09.2015