В чем разница между подпроцессом Popen и call (как я могу их использовать)? - PullRequest
161 голосов
/ 07 октября 2011

Я хочу вызвать внешнюю программу из Python.Для этого я использовал Popen() и call().

В чем разница между ними?

Моя конкретная цель - запустить следующую команду из Python.Я не уверен, как работают перенаправления.

./my_script.sh > output

Я прочитал документацию и там говорится, что call() - это вспомогательная функция или функция быстрого доступа.Мы теряем какую-либо силу, используя call() вместо Popen()?

1 Ответ

238 голосов
/ 07 октября 2011

Есть два способа сделать перенаправление.Оба применяются к subprocess.Popen или subprocess.call.

  1. Установите аргумент ключевого слова shell = True или executable = /path/to/the/shell и укажите команду так, как она у вас есть.

  2. Поскольку вы просто перенаправляете вывод в файл, установите ключевое слово аргумента

    stdout = an_open_writeable_file_object
    

    , где объект указывает на файл output.

subprocess.Popen является более общим, чем subprocess.call.

Popen не блокирует, позволяя вам взаимодействовать с процессомпока он работает, или продолжайте заниматься другими вещами в вашей программе на Python.Вызов Popen возвращает объект Popen.

call делает блок.Несмотря на то, что он поддерживает все те же аргументы, что и конструктор Popen, вы все равно можете установить «выходные данные процесса, переменные среды и т. Д.», Но ваш сценарий ожидает завершения программы, а call возвращает код, представляющий процесс ».статус выхода.

returncode = call(*args, **kwargs) 

- это то же самое, что вызов

returncode = Popen(*args, **kwargs).wait()

call - это просто вспомогательная функция.Его реализация в CPython находится в subprocess.py :

def call(*popenargs, timeout=None, **kwargs):
    """Run command with arguments.  Wait for command to complete or
    timeout, then return the returncode attribute.

    The arguments are the same as for the Popen constructor.  Example:

    retcode = call(["ls", "-l"])
    """
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

Как видите, это тонкая оболочка вокруг Popen.

...