Есть четыре веских аргумента в пользу предпочтения более специфических методов 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")
Есть много таких команд, которые могут поставить вашу систему под угрозу.