Есть четыре веских аргумента в пользу предпочтения более специфических методов Python в os
модуле, чем при использовании os.system
или subprocess
модуле при выполнении команды:
- Избыточность - порождение другого процесса является избыточным и тратит время и ресурсы.
- Переносимость - многие из методов в
os
модуле доступны на нескольких платформах, в то время как многие команды оболочки зависят от ОС.
- Понимание результатов - порождение процесса для выполнения произвольных команд вынуждает вас анализировать результаты из вывода и понимать, если и почему команда сделала что-то не так.
- Безопасность - процесс может потенциально выполнить любую команду, которую ему дают. Это слабый дизайн, и его можно избежать, используя специальные методы в
os
модуле.
Вы фактически выполняете избыточного «посредника» на пути к возможным системным вызовам (chmod
в вашем примере). Этот средний человек - это новый процесс или суб-оболочка.
От os.system
:
Выполнить команду (строку) в подоболочке ...
И subprocess
это просто модуль для порождения новых процессов.
Вы можете делать то, что вам нужно, не вызывая эти процессы.
Переносимость (см. Переносимость исходного кода ):
Целью os
модуля является предоставление общих служб операционной системы, и его описание начинается с:
Этот модуль предоставляет портативный способ использования функциональных возможностей, зависящих от операционной системы.
Вы можете использовать os.listdir
как на Windows, так и на Unix. Попытка использовать os.system
/ subprocess
для этой функции заставит вас выполнить два вызова (для ls
/ dir
) и проверить, в какой операционной системе вы работаете. Это не так переносимо и позже приведет к еще большему разочарованию (см. Обработка вывода ).
Понимание результатов команды:
Предположим, вы хотите перечислить файлы в каталоге.
Если вы используете os.system("ls")
/subprocess.call(['ls'])
, вы можете получить только выходные данные процесса, которые в основном представляют собой большую строку с именами файлов.
Как вы можете отличить файл с пробелом в имени от двух файлов?
Что если у вас нет разрешения перечислять файлы?
Как вы должны отобразить данные на объекты Python?
Это только из головы, и, хотя есть решения этих проблем - зачем снова решать проблему, которая была решена для вас?
Это пример того , чтобы следовать не повторяйте себя принцип (часто обозначаемый как «DRY») по не повторять реализацию , которая уже существует и свободно доступны для вас.
Безопасность:
os.system
и subprocess
мощные. Это хорошо, когда тебе нужна эта сила, но это опасно, когда тебе это не нужно. Когда вы используете os.listdir
, вы знаете, что он не может делать ничего другого, кроме списка файлов или выдавать ошибку. Когда вы используете os.system
илиsubprocess
для достижения того же поведения, вы можете в конечном итоге сделать то, что вы не хотели делать.
Безопасность впрыска (см. Примеры инъекций в оболочку ) :
Если вы используете ввод от пользователя в качестве новой команды, вы в основном дали ему оболочку. Это очень похоже на SQL-инъекцию, предоставляющую пользователю оболочку в БД.
Примером может служить команда вида:
# ... read some user input
os.system(user_input + " some continutation")
Это может быть легко использовано для запуска любого произвольного кода, используя input: NASTY COMMAND;#
для создания возможного:
os.system("NASTY COMMAND; # some continuation")
Есть много таких команд, которые могут поставить вашу систему под угрозу.