Яка різниця між підпроцесом Popen і викликом (як я можу їх використовувати)?


178

Я хочу зателефонувати до зовнішньої програми від Python. Я використав і те, Popen()і call()це зробити.

Яка різниця між ними?

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

./my_script.sh > output

Я читаю документацію, і там написано, що call()це зручність або функція швидкого доступу. Чи втрачаємо ми якусь силу, використовуючи call()замість Popen()?


Яка частина документації вас бентежила? Визначення 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.


17
В основному Popen і call - це асинхронні та синхронні функції, які відповідно використовуються для запуску команд Linux.
user3016020

1
Яка перевага використання Popen? Чи не було б безпечно чекати, поки викликана програма закінчиться спочатку?
Том

4
@ Часто ні. Що робити, якщо ви хочете прочитати деякий вихід, а потім надіслати більше вводу в програму, прочитати більше виводу, що виходить з цього вводу, повторити?
agf

@ user3016020 Я припускаю, що це стосується і команд Windows? Правильно?
domih

7

Інша відповідь дуже повна, але ось головне правило:

  • call блокує:

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

    Popen('notepad.exe')
    print('hello')  # immediately executed
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.