Інші відповіді тут належним чином пояснюють застереження щодо безпеки, які також згадуються в subprocess
документації. Але крім цього, накладні витрати на запуск оболонки для запуску програми, яку ви хочете запустити, часто непотрібні і, безумовно, нерозумні для ситуацій, коли ви фактично не використовуєте жодної з функцій оболонки. Більше того, додаткова прихована складність повинна вас налякати, особливо якщо ви не дуже знайомі з оболонкою або послугами, які вона надає.
Там, де взаємодія з оболонкою нетривіальна, тепер ви вимагаєте від читача та підтримувача сценарію Python (який може бути, а може і не бути вашим майбутнім "), щоб зрозуміти і Python, і сценарій оболонки. Запам’ятайте девіз Python «явне краще, ніж неявне»; навіть коли код Python буде дещо складнішим, ніж еквівалентний (і часто дуже короткий) скрипт оболонки, вам може бути краще видалити оболонку та замінити функціональність на рідними конструкціями Python. Мінімізація роботи, виконаної у зовнішньому процесі, і максимально тримати контроль над власним кодом, часто є хорошою ідеєю просто тому, що це покращує видимість і зменшує ризики виникнення бажаних або небажаних побічних ефектів.
Розширення підстановки, змінна інтерполяція та перенаправлення все просто замінити рідними конструкціями Python. Складний конвеєр оболонки, де частини або все неможливо розумно переписати на Python, була б єдиною ситуацією, коли, можливо, ви могли б розглянути можливість використання оболонки. Ви все ж повинні переконатися, що ви розумієте наслідки для продуктивності та безпеки.
У тривіальному випадку, щоб уникнути shell=True
, просто замініть
subprocess.Popen("command -with -options 'like this' and\\ an\\ argument", shell=True)
з
subprocess.Popen(['command', '-with','-options', 'like this', 'and an argument'])
Зверніть увагу, як перший аргумент - це список рядків для передачі execvp()
та як цитування рядків та метахарактерів оболонки, що ухиляються від косої риски, як правило, не потрібні (або корисні, або правильні). Можливо, див. Також Коли обернути лапки навколо змінної оболонки?
Як сторону, ви дуже часто хочете уникнути, Popen
якщо одна з простіших subprocess
упаковок в упаковці робить те, що ви хочете. Якщо у вас є нещодавній Python, ви, ймовірно, повинні використовувати subprocess.run
.
- З
check=True
нею не вдасться, якщо команда, яку ви виконували, не вдалася.
- З
stdout=subprocess.PIPE
його допомогою буде фіксуватися вихід команди.
- Дещо незрозуміло,
universal_newlines=True
він буде декодувати вихід у відповідний рядок Unicode (це просто bytes
в системі, що кодує інакше, на Python 3).
Якщо ні, то для багатьох завдань потрібно check_output
отримати результат з команди, перевіривши, чи вдалося це зробити, чи check_call
немає виводу для збору.
Закінчу цитатою Девіда Корна: "Простіше написати портативний оболонку, ніж сценарій портативної оболонки". Навіть subprocess.run('echo "$HOME"', shell=True)
не є портативним для Windows.
-l
передається в/bin/sh
(оболонку) замістьls
програми на Unix, якщоshell=True
. Аргумент рядка слід використовуватиshell=True
в більшості випадків замість списку.