Вот краткое описание способов вызова внешних программ и преимуществ и недостатков каждого из них:
os.system("some_command with args")
передает команду и аргументы в оболочку вашей системы. Это хорошо, потому что вы можете запускать сразу несколько команд таким образом и настраивать каналы и перенаправление ввода / вывода. Например: os.system("some_command < input_file | another_command > output_file")
Однако, хотя это удобно, вы должны вручную обрабатывать экранирование символов оболочки, таких как пробелы и т. Д. С другой стороны, это также позволяет запускать команды, которые являются просто командами оболочки, а не фактически внешними программами , См. документацию . stream = os.popen("some_command with args")
будет делать то же самое, что и os.system
, за исключением того, что он дает файл-подобный объект, который вы можете использовать для доступа к стандартному вводу / выводу для этого процесса. Есть еще 3 варианта popen, которые все обрабатывают i / o немного по-другому. Если вы передаете все как строку, ваша команда передается в оболочку; если вы передадите их в список, то вам не нужно беспокоиться о том, чтобы избежать чего-либо. См. документацию . Popen
модуля subprocess
. Это предназначено для замены os.popen
, но имеет недостаток в том, что он немного усложняется благодаря тому, что он настолько всеобъемлющий. Например, вы могли бы сказать: print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
вместо: print os.popen("echo Hello World").read()
, но хорошо иметь все варианты там в одном унифицированном классе вместо 4 различных функций popen. См. документацию . call
из модуля subprocess
. Это в основном так же, как класс Popen
, и принимает все те же аргументы, но он просто ждет, пока команда не завершится, и вы получите код возврата. Например: return_code = subprocess.call("echo Hello World", shell=True)
См. документацию . subprocess.run
, что очень похоже на выше, но еще более гибкое и возвращает объект CompletedProcess
, когда команда завершает выполнение. Возможно, модуль subprocess
- это то, что вы используете.
Наконец, имейте в виду, что для всех методов, в которых вы передаете окончательную команду для выполнения оболочкой в виде строки, и вы несете ответственность за ее выход из нее. Имеются серьезные последствия для безопасности, если какая-либо часть передаваемой строки не может быть полностью доверена. Например, если пользователь вводит какую-либо / любую часть строки. Если вы не уверены, используйте эти методы только с константами. Чтобы дать вам намек на последствия, рассмотрите этот код:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
и представьте, что пользователь вводит «моя мама не любила меня & amp; & amp; rm -rf /".