Pozostałe odpowiedzi w odpowiedni sposób wyjaśniają zastrzeżenia bezpieczeństwa, które są również wymienione w subprocess
dokumentacji. Ale oprócz tego narzut związany z uruchomieniem powłoki w celu uruchomienia programu, który chcesz uruchomić, jest często niepotrzebny i zdecydowanie głupi w sytuacjach, w których nie używasz żadnej z funkcji powłoki. Co więcej, dodatkowa ukryta złożoność powinna cię wystraszyć, szczególnie jeśli nie znasz dobrze powłoki lub usług, które ona zapewnia.
Tam, gdzie interakcje z powłoką są nietrywialne, musisz teraz czytać i utrzymywać skrypt Pythona (który może, ale nie musi być twoim przyszłym ja), aby zrozumieć zarówno Python, jak i skrypt powłoki. Pamiętaj motto Pythona „wyraźne jest lepsze niż niejawne”; nawet jeśli kod Pythona będzie nieco bardziej skomplikowany niż równoważny (i często bardzo zwięzły) skrypt powłoki, lepiej jest usunąć powłokę i zastąpić funkcjonalność natywnymi konstrukcjami Pythona. Minimalizowanie pracy wykonanej w procesie zewnętrznym i utrzymywanie kontroli nad własnym kodem w miarę możliwości jest często dobrym pomysłem, ponieważ poprawia widoczność i zmniejsza ryzyko pożądanych lub niepożądanych efektów ubocznych.
Rozszerzanie symboli wieloznacznych, interpolacja zmiennych i przekierowanie można łatwo zastąpić natywnymi konstrukcjami języka Python. Złożony potok powłoki, w którym części lub wszystkich nie można w rozsądny sposób przepisać w Pythonie, byłby jedyną sytuacją, w której można rozważyć użycie powłoki. Nadal upewnij się, że rozumiesz wpływ na wydajność i bezpieczeństwo.
W trywialnym przypadku, aby tego uniknąć shell=True
, wystarczy wymienić
subprocess.Popen("command -with -options 'like this' and\\ an\\ argument", shell=True)
z
subprocess.Popen(['command', '-with','-options', 'like this', 'and an argument'])
Zauważ, że pierwszym argumentem jest lista ciągów, które należy przekazać execvp()
, i w jaki sposób cytowanie ciągów i metaznaków powłoki odwracających ukośnik nie jest generalnie konieczne (ani przydatne, ani poprawne). Może zobacz także Kiedy zawijać cudzysłowy wokół zmiennej powłoki?
Nawiasem mówiąc, bardzo często chcesz uniknąć, Popen
jeśli jeden z prostszych opakowań w subprocess
pakiecie robi to, co chcesz. Jeśli masz dość najnowszego Pythona, prawdopodobnie powinieneś go użyć subprocess.run
.
- Dzięki
check=True
nie powiedzie się, jeśli uruchomione polecenie nie powiedzie się.
- Dzięki
stdout=subprocess.PIPE
niemu przechwyci wynik polecenia.
- Nieco niejasno, dzięki
universal_newlines=True
niemu dekoduje dane wyjściowe do odpowiedniego łańcucha Unicode (inaczej jest to tylko bytes
systemowe kodowanie w Pythonie 3).
Jeśli nie, w przypadku wielu zadań chcesz check_output
uzyskać dane wyjściowe z polecenia, sprawdzając, czy się powiodło, lub check_call
czy nie ma danych wyjściowych do zebrania.
Zakończę cytatem Davida Korna: „Łatwiej jest napisać przenośną powłokę niż przenośny skrypt powłoki”. Nawet subprocess.run('echo "$HOME"', shell=True)
nie jest przenośny na Windows.
-l
jest przekazywane do/bin/sh
(powłoki) zamiastls
programu w Uniksie, jeślishell=True
.shell=True
W większości przypadków należy użyć argumentu ciągu zamiast listy.