2017-01-16 5 views
2

Кажется, что он выполняет подпроцесс и создает канал для ввода/вывода, только что подпроцесс более новый.Python: когда следует использовать subprocess.Popen вместо os.popen?

Мой вопрос в том, есть ли какая-либо функция, которую может выполнять подпроцесс.Popen, в то время как os.popen не может, так что нам нужен новый подпроцесс?

Почему язык python не решил повысить os.popen, но создал новый модуль?

Благодаря

+4

От https://docs.python.org/2/library/os.html#os.popen «Устаревший с версии 2.6: эта функция устарела. Используйте модуль« subprocess ». –

+2

См. Https: //www.python.org/dev/peps/pep-0324/Секции мотивации и обоснования: защита от некоторых угроз безопасности, исключений между процессами, улучшение операций с файловым дескриптором и т. д. –

+1

Помимо проблем безопасности и надежности, IMHO, старые 'os. семья поп-ром была громоздкой и запутанной. Практически невозможно было правильно использовать, не обращаясь к документам во время кодирования. Для сравнения, «подпроцесс» - это находка, хотя по-прежнему разумно ссылаться на документы во время его использования. ;) –

ответ

6

Короткий ответ: Никогда не используйте os.popen, всегда используйте subprocess!

Как вы можете видеть из Python 2.7 os.popen docs:

Устаревший начиная с версии 2.6: Эта функция устарела. Используйте модуль subprocess. Особенно проверьте раздел Replacing Older Functions with the subprocess Module.

Существовали различные ограничения и проблемы со старым семейством функций os.popen. Как упоминалось в документах, версии до 2.6 не были даже надежными в Windows.

Мотивация subprocess объясняется в PEP 324 -- subprocess - New process module:

Мотивация

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

  • Неуместные функции для запуска процессов может означать риск в безопасности: Если программа запущена через оболочку, и аргументы содержат оболочки мета-символы, результат может быть катастрофическим. [1]

  • Это делает Python еще более понятным языком замены для чрезмерно сложных сценариев оболочки.

В настоящее время Python имеет большое количество различных функций для создания процесса. Это затрудняет выбор разработчикам.

Модуль подпроцесс обеспечивает следующие усовершенствования по сравнению с предыдущими функций:

  • Один «единый» модуль обеспечивает все функции от предыдущих функций.

  • Исключения перекрестного процесса: Исключения, происходящие в дочернем объекте перед тем, как новый процесс начал выполняться, повторно возникают в родительском элементе. Это означает, что легко обрабатывать ошибки exec() , например.Например, с popen2 невозможно обнаружить, не удалось ли выполнить выполнение. .

  • Крючок для выполнения пользовательского кода между fork и exec. Это может быть использован для замены, например, uid.

  • Неявный вызов/bin/sh. Это означает, что нет необходимости в для экранирования метасимволов опасных оболочек.

  • Возможны все комбинации перенаправления дескриптора файла. Например, «python-dialog» [2] должен вызвать процесс и перенаправить stderr, но не stdout. Это невозможно с текущими функциями без использования временных файлов.

  • С модулем подпроцесса можно управлять, если все открытые дескрипторы файла должны быть закрыты до выполнения новой программы .

  • Поддержка подключения нескольких подпроцессов (оболочка «труба»).

  • Универсальная поддержка новой строки.

  • Метод связи(), который позволяет легко отправлять данные stdin и читать данные stdout и stderr, не рискуя взаимными ошибками. Большинство людей осведомлены о проблемах управления потоком, связанных с подключением к дочернему процессу , но не у всех есть терпение или навыков для написания полностью правильного и беззаботного цикла выбора. Это означает, что многие приложения Python содержат гонку условий. Метод communication() в стандартной библиотеке решает эту проблему.

Пожалуйста, смотрите ссылку PEP для Обоснование и дополнительные детали.

Помимо безопасности & вопросы надежности, ИМХО, старые os.popen семья была громоздкой и запутанной. Практически невозможно было правильно использовать, не обращаясь к документам во время кодирования. Для сравнения, subprocess - это находка, хотя по-прежнему разумно обращаться к документам при их использовании. ;)

Иногда люди рекомендуют использовать os.popen вместо subprocess.Popen в Python 2.7, например Python subprocess vs os.popen overhead, потому что это быстрее. Конечно, это быстрее, но это потому, что он не выполняет различные вещи, которые жизненно важны, чтобы гарантировать, что он работает безопасно!


FWIW, os.popen itself still exists in Python 3, однако это безопасно реализовано с помощью subprocess.Popen, так что вы можете также просто использовать subprocess.Popen непосредственно сами. Остальные члены семейства os.popen больше не существуют в Python 3. Семейство функций os.spawn все еще существует в Python 3, но в документах рекомендуется использовать более мощные средства, предоставляемые модулем subprocess.