Как открыть подпроцесс во время выполнения другого?

#python

#python

Вопрос:

Я пытаюсь создать программу запуска приложений, но она не работает, пока работает другой подпроцесс. Я запускаю firefox, но другие задачи выполняются только тогда, когда окно с firefox закрыто. Код:

 import subprocess
while True:
    app = input('>>> ')
    subprocess.call(app)
 

Пример: я запускаю приложение и запускаю веб-браузер, затем набираю «atom» и «leafpad», чтобы открыть их, но они становятся завершенными только тогда, когда окно с браузером закрыто.

Ответ №1:

Вы могли бы создать поток, который выполняет subprocess.call команду.

Дешевым трюком было бы заменить subprocess.call на subprocess.Popen

 import subprocess
while True:
    app = input('>>> ')
    subprocess.Popen(app)
 

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

Как только Popen вызывается и процесс запускается, скрипт python возобновляется.

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

Чтобы убедиться, что процесс был запущен, все же лучше создать поток и вызвать subprocess.call в этом потоке (блокирующий, но в потоке) и проверить код возврата.

Ответ №2:

subprocess.call и subprocess.run дождитесь завершения. Если вам нужны асинхронные процессы, вам нужно использовать subprocess.Popen напрямую.

Пример из тестового примера, в котором проверяется связь между двумя процессами:

     sub_pro = Popen(tst_subscriber, stdout=subprocess.PIPE, env=test_env)
    pub_pro = Popen(tst_publisher, stdout=subprocess.PIPE, env=test_env)

    timeout_sub = Timer(timeout, kill_subscriber, [sub_pro])
    timeout_pub = Timer(timeout, kill_publisher, [pub_pro])

    timeout_sub.start()
    timeout_pub.start()
    (output, err) = sub_pro.communicate()