Python - Когда это нормально использовать os.system() для выдачи общих команд Linux

Отключение от другого потока, когда целесообразно использовать os.system() для выдачи команд, таких как rm -rf, cd, make, xterm, ls?

Учитывая, что существуют аналоговые версии вышеуказанных команд (кроме make и xterm), я полагаю, что использовать эти встроенные команды python безопаснее, вместо использования os.system()

Любые мысли? Я бы хотел их услышать.

Ответ 1

Правило большого пальца: если для достижения этой функциональности встроенная функция Python использует эту функцию. Зачем? Это делает ваш код переносимым в разных системах, более безопасным и, вероятно, быстрее, так как не потребуется создавать дополнительный процесс.

Ответ 2

Одна из проблем с system() заключается в том, что она подразумевает знание синтаксиса оболочки и языка для синтаксического анализа и выполнения командной строки. Это создает вероятность ошибки, при которой вы не правильно проверяете ввод, и оболочка может интерпретировать что-то вроде замены переменных или определения того, где аргумент начинается или заканчивается таким образом, которого вы не ожидаете. Кроме того, другая оболочка ОС может иметь разный синтаксис от вашего собственного, включая очень тонкую дивергенцию, которую вы не заметите сразу. По причинам, подобным этим, я предпочитаю использовать execve() вместо system() - вы можете передавать токены argv напрямую и не должны беспокоиться о чем-то посередине (неверно), анализируя ваш ввод.

Другая проблема с system() (это также относится к использованию execve()) заключается в том, что когда вы это кодируете, вы говорите: "Ищите эту программу и передавайте ей эти аргументы". Это делает несколько допущений, которые могут привести к ошибкам. Во-первых, программа существует и может быть найдена в $PATH. Возможно, в какой-то системе этого не произойдет. Во-вторых, возможно, в какой-то системе или даже в будущей версии вашей собственной ОС она будет поддерживать другой набор параметров. В этом смысле я бы избегал делать это, если вы не уверены, что система, в которой вы будете работать, будет иметь программу. (Как, может быть, вы положили программу вызова в систему, чтобы начать с нее, или способ, которым вы ее вызываете, подкреплен чем-то вроде POSIX.)

Наконец... Также наблюдается поражение производительности, связанное с поиском правильной программы, созданием нового процесса, загрузкой программы и т.д. Если вы делаете что-то простое, как mv, гораздо эффективнее использовать системный вызов.

Это лишь некоторые из причин, чтобы избежать system(). Конечно, их больше.

Ответ 3

Ответ Дарина - хорошее начало.

Кроме того, это вопрос о том, насколько портативны вы планируете быть. Если ваша программа будет работать только на достаточно "стандартной" и "современной" Linux, тогда вам не будет причин повторно изобретать колесо; если вы попытаетесь перезаписать make или xterm, они отправят вас в белые пальто. Если это работает, и у вас нет проблем с платформой, выбейте себя и просто используйте Python в качестве клея!

Если совместимость в неизвестных системах была большой проблемой, вы могли бы попытаться найти библиотеки для выполнения необходимых действий независимо от платформы. Или вам нужно изучить способ вызова встроенных утилит с разными именами, путями и механизмами в зависимости от того, в какой системе вы находитесь.

Ответ 4

Ваш вопрос, кажется, состоит из двух частей. Вы упомянули вызовы, такие как "xterm", "rm -rf" и "cd".

Боковое примечание: вы не можете вызвать 'cd' в под-оболочке. Уверен, что это был трюк...

Что касается других вещей на уровне команд, которые вы, возможно, захотите сделать, например "rm -rf SOMETHING", то уже есть эквивалент python. Это отвечает на первую часть вашего вопроса. Но я подозреваю, что вы действительно спрашиваете о второй части.

Вторая часть вашего вопроса может быть перефразирована как "следует ли использовать систему() или что-то вроде модуля подпроцесса?".

У меня есть простой ответ для вас: просто скажите "НЕТ" использовать "system()", за исключением прототипирования.

Это отлично подходит для проверки того, что что-то работает, или для этого "быстрого и грязного" script, но слишком много проблем с os.system():

  • Он разворачивает оболочку для вас - отлично, если вам нужно
  • Он расширяет для вас дикие карты - отлично, если у вас нет никаких
  • Он обрабатывает перенаправление - отлично, если вы хотите, чтобы
  • Он выгружает вывод в stderr/stdout и считывает из stdin по умолчанию
  • Он пытается понять цитирование, но это не очень хорошо (попробуйте "Cmd" > "Ofile" )
  • Связано С# 5, оно не всегда ограничивает границы аргументов (т.е. аргументы с пробелами в них могут быть испорчены)

Просто скажи "нет" "system()"!

Ответ 5

Единственным моментом, когда подходит os.system, является быстрое и грязное решение для непроизводственного script или какого-либо тестирования. В противном случае лучше использовать встроенные функции.

Ответ 6

Я бы предположил, что вы используете только os.system для вещей, которые еще не эквивалентны в модуле os. Зачем делать вашу жизнь труднее?

Ответ 7

В python вызов os.system начинает "нахмуриться". "Новая" замена будет subprocess.call или subprocess.Popen в модуле подпроцесса. Проверьте документы для subprocess

Другая приятная вещь в подпроцессе: вы можете читать stdout и stderr в переменные и обрабатывать, чтобы без необходимости перенаправления на другие файлы.

Как и другие, упомянутые выше, есть модули для большинства вещей. Если вы не пытаетесь приклеить много других команд, я буду придерживаться вещей, включенных в библиотеку. Если вы копируете файлы, используйте shutal, работая с архивами, у вас есть модули, такие как tarfile/zipfile и т.д.

Удачи.