Оператор if-then bash как последовательность в подпроцессе python

Есть ли способ выполнить инструкцию bash if-then как последовательность в подпроцессе Python? Я могу выполнить инструкцию if-then как строку, но я хочу преобразовать ее в последовательность для более безопасного кода.

Это моя программа на данный момент. Он использует строку в качестве первого входа подпроцесса с аргументом shell=True.

# this example works
import subprocess
p = subprocess.Popen('if [ ! -d "dir1" ]; then mkdir dir1; fi;', shell=True)

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

# this example does not work
import subprocess
p = subprocess.Popen(['if','[ ! -d "dir1" ];','then','mkdir','dir1;','fi;'], shell=False)

Каждый токен должен быть отдельным элементом списка. shlex.split() сделает это за вас. А еще лучше не делайте этого в оболочке, если Python может делать это отлично.

kindall 10.08.2018 17:03

Ваш код bash можно легко преобразовать в чистый Python. Нет необходимости задействовать подпроцессы.

jwodder 10.08.2018 17:04

По крайней мере, в этом примере вы можете просто использовать ['mkdir', '-p', 'dir1']; нет необходимости в операторе if (который, как пример синтаксиса оболочки, будет требоватьshell=True, поскольку if не является внешней командой).

chepner 10.08.2018 17:04
0
3
244
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

if - это ключевое слово оболочки, а не внешняя команда, поэтому вам не следует использовать аргумент списка; строка должна быть проанализирована и выполнена оболочкой. (Вы можете использовать shell=True со списком, но это бессмысленно, поскольку Popen в любом случае должен объединять элементы списка в одну строку.)

Однако вам не нужен оператор оболочки if для этого конкретного примера, поскольку опция -p для mkdir укажет ему создать каталог только в том случае, если он еще не завершился.

p = subprocess.Popen(["mkdir", "-p", "dir1"])

Кроме того, вам не нужен подпроцесс в все, потому что Python предоставляет свою собственную оболочку для системного вызова, который создает каталог.

try:
    os.mkdir("dir1")
except FileExistsError:
    pass

(Поймайте и проигнорируйте исключение, а не проверяйте, существует ли сначала каталог, чтобы избежать состояния гонки, когда кто-то может создать каталог после того, как вы его проверите, но до того, как вы действительно попытаетесь его создать.)

docs.python.org/3/library/pathlib.html#pathlib.Path.mkdir тоже выглядит актуальным: Path("dir1").mkdir(exist_ok = True)
melpomene 10.08.2018 17:11

Хороший. Я еще особо не смотрел на pathlib.

chepner 10.08.2018 17:36

Другие вопросы по теме