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

178

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

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

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

./my_script.sh > output

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

varunl
источник
Какая часть документации вас смутила? Определение call()кажется очень ясным. Можете ли вы предоставить цитату или ссылку, чтобы мы знали, на что обратить внимание в ответе?
S.Lott

Ответы:

265

Есть два способа сделать перенаправление. Оба относятся к любому 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.

AGF
источник
17
В основном, Popen и call являются асинхронными и синхронными функциями, соответственно используемыми для запуска команд Linux.
user3016020 13.12.15
1
В чем преимущество использования popen? Разве не было бы безопасно ждать, пока вызываемая программа не завершится первой?
Том
4
@ Том часто нет. Что если вы хотите прочитать какой-то вывод, затем отправить больше входных данных в программу, прочитать больше выходных данных, полученных в результате этого ввода, повторить?
agf
@ user3016020 Я полагаю, это также относится к командам Windows? Правильно?
Домих
7

Другой ответ очень полный, но вот практическое правило:

  • call блокирует:

    call('notepad.exe')
    print('hello')  # only executed when notepad is closed
    
  • Popen не блокирует:

    Popen('notepad.exe')
    print('hello')  # immediately executed
    
Basj
источник