Я называю разные процессы с subprocess
модулем. Однако у меня есть вопрос.
В следующих кодах:
callProcess = subprocess.Popen(['ls', '-l'], shell=True)
и
callProcess = subprocess.Popen(['ls', '-l']) # without shell
Оба работают. Прочитав документы, я узнал, что это shell=True
означает выполнение кода через оболочку. Таким образом, это означает, что в отсутствие процесс запускается напрямую.
Итак, что я предпочитаю для своего случая - мне нужно запустить процесс и получить его вывод. Какую выгоду я получаю от вызова изнутри или снаружи.
python
subprocess
user225312
источник
источник
-l
передается/bin/sh
(оболочке) вместоls
программы в Unix, еслиshell=True
. Строковый аргумент должен использоватьсяshell=True
в большинстве случаев вместо списка.shell=True
наFalse
и наоборот является ошибкой. Из документации : «В POSIX с shell = True, (...) Если args является последовательностью, первый элемент задает командную строку, а любые дополнительные элементы будут рассматриваться как дополнительные аргументы для самой оболочки.». В Windows есть автоматическое преобразование , которое может быть нежелательным.Ответы:
Преимущество отказа от вызова через оболочку состоит в том, что вы не вызываете «загадочную программу». В POSIX переменная среды
SHELL
определяет, какой двоичный файл вызывается как «оболочка». В Windows нет потомка оболочки Bourne, только cmd.exe.Таким образом, вызов оболочки вызывает программу по выбору пользователя и зависит от платформы. Вообще говоря, избегайте вызовов через оболочку.
Вызов через оболочку позволяет расширять переменные среды и файловые глобусы в соответствии с обычным механизмом оболочки. В системах POSIX оболочка расширяет файловые глобусы до списка файлов. В операционной системе Windows, файл - Глоб (например, «*. *») Не расширяется за счет оболочки, так или иначе (но переменные окружения в командной строке будут расширены cmd.exe).
Если вы считаете, что вам нужны расширения переменных среды и глобусы файлов, изучите
ILS
атаки 1992-го года на сетевые службы, которые выполняли вызовы подпрограмм через оболочку. Примеры включают в себя различныеsendmail
бэкдоры с участиемILS
.В заключение, используйте
shell=False
.источник
$SHELL
неверно. Процитируем subprocess.html: «В Unix сshell=True
оболочкой по умолчанию/bin/sh
.» (не$SHELL
)open
если вы хотите использовать безопасные способы вызова программы и получения результатов.источник: модуль подпроцесса
источник
Пример, где все может пойти не так с Shell = True, показан здесь
Проверьте документ здесь: subprocess.call ()
источник
Выполнение программ через оболочку означает, что весь пользовательский ввод, передаваемый в программу, интерпретируется в соответствии с синтаксическими и семантическими правилами вызванной оболочки. В лучшем случае это только доставляет неудобства пользователю, потому что пользователь должен соблюдать эти правила. Например, пути, содержащие специальные символы оболочки, такие как кавычки или пробелы, должны быть экранированы. В худшем случае это приводит к утечкам безопасности, поскольку пользователь может выполнять произвольные программы.
shell=True
иногда удобно использовать определенные функции оболочки, такие как разделение слов или расширение параметров. Однако, если такая функция требуется, используйте другие модули (например,os.path.expandvars()
для расширения параметров илиshlex
для разделения слов). Это означает больше работы, но позволяет избежать других проблем.Короче говоря: избегайте во что
shell=True
бы то ни стало.источник
Другие ответы здесь адекватно объясняют предостережения безопасности, которые также упоминаются в
subprocess
документации. Но в дополнение к этому, издержки запуска оболочки для запуска программы, которую вы хотите запустить, часто не нужны и, безусловно, глупы в ситуациях, когда вы фактически не используете какую-либо функциональность оболочки. Более того, дополнительная скрытая сложность должна пугать вас, особенно если вы не очень хорошо знакомы с оболочкой или предоставляемыми ей службами.Там, где взаимодействия с оболочкой нетривиальны, теперь вам требуется, чтобы читатель и сопровождающий сценария Python (который может быть вашим будущим я или не мог) понимал как Python, так и сценарий оболочки. Помните девиз Python «явное лучше, чем неявное»; даже если код Python будет несколько более сложным, чем эквивалентный (и часто очень краткий) сценарий оболочки, вам может быть лучше удалить оболочку и заменить функциональность собственными конструкциями Python. Минимизация работы, выполняемой во внешнем процессе, и сохранение контроля в собственном коде, насколько это возможно, часто является хорошей идеей просто потому, что она улучшает видимость и снижает риски нежелательных или нежелательных побочных эффектов.
Расширение подстановочных знаков, интерполяция переменных и перенаправление - все это легко заменить на собственные конструкции Python. Сложный конвейер оболочки, где части или все не могут быть разумно переписаны в Python, был бы единственной ситуацией, когда вы могли бы рассмотреть возможность использования оболочки. Вы все равно должны убедиться, что понимаете последствия для производительности и безопасности.
В тривиальном случае, чтобы избежать
shell=True
, просто заменитес участием
Обратите внимание, как первый аргумент представляет собой список строк для передачи
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.источник
shell=True
, многие с отличными ответами. Вы случайно выбрали ту, которая о том, почему вместо этого.subprocess