Інші відповіді тут належним чином пояснюють застереження щодо безпеки, які також згадуються в 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в більшості випадків замість списку.