Команда Python popen. Дождитесь завершения команды


79

У меня есть сценарий, в котором я запускаю команду popen a shell. Проблема в том, что сценарий не дожидается завершения выполнения этой команды popen и сразу же продолжает работу.

om_points = os.popen(command, "w")
.....

Как я могу сказать своему скрипту Python дождаться завершения команды оболочки?

Ответы:


112

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

#start and block until done
subprocess.call([data["om_points"], ">", diz['d']+"/points.xml"])

Если вы хотите что-то делать во время его выполнения или загружать что-то stdin, вы можете использовать communicateпосле popenвызова.

#start and process things, then wait
p = subprocess.Popen([data["om_points"], ">", diz['d']+"/points.xml"])
print "Happens while running"
p.communicate() #now wait plus that you can send commands to process

Как указано в документации, waitвозможна взаимоблокировка, поэтому желательно общаться.


Ознакомьтесь с документацией на subprocess.call
thornomad

Хотя подпроцесс является предпочтительным во многих ответах, он не может очень хорошо обрабатывать пространство и квоту в команде. Приведенный выше ответ не решает напрямую вопрос os.popen.
Чанг

подпроцесс может быть до 2 раз медленнее, чем система ОС
MonsieurBeilto,

subprocess.run()был добавлен в Python 3.5 и представляет собой «Рекомендуемый подход к
вызову

29

Вы можете использовать subprocessдля этого.

import subprocess

#This command could have multiple commands separated by a new line \n
some_command = "export PATH=$PATH://server.sample.mo/app/bin \n customupload abc.txt"

p = subprocess.Popen(some_command, stdout=subprocess.PIPE, shell=True)

(output, err) = p.communicate()  

#This makes the wait possible
p_status = p.wait()

#This will give you the output of the command being executed
print "Command output: " + output

подпроцесс может быть до 2 раз медленнее, чем система ОС
MonsieurBeilto,

12

Принудительно popenне продолжать, пока не будет прочитан весь вывод, выполнив:

os.popen(command).read()

2
Я не эксперт по питону, но это, пожалуй, самое простое решение, которое вносит наименьшее количество изменений в исходный код. Есть ли причина, по которой это не было бы хорошим решением?
jdmcnair

7

Пусть команда, которую вы пытаетесь передать, будет

os.system('x')

затем вы превращаете это в заявление

t = os.system('x')

теперь питон будет ждать вывода из командной строки, чтобы его можно было присвоить переменной t.


4

Вы ищете waitметод.


Но если я наберу: om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points.xml", "w"). Wait (), я получаю эту ошибку: Traceback (последний вызов последний): файл "./model_job.py", строка 77, в <module> om_points = os.popen (data ["om_points"] + ">" + diz ['d'] + "/ points .xml "," w "). wait () AttributeError: объект 'file' не имеет атрибута 'wait' В чем проблема? Еще раз спасибо.
Мишель

12
Вы не нажимали на предоставленную мной ссылку. waitэто метод subprocessкласса.
Оливье Вердье

1
ожидание может
зайти в

подпроцесс может быть до 2 раз медленнее, чем система ОС
MonsieurBeilto,

2

wait () отлично работает для меня. Подпроцессы p1, p2 и p3 выполняются одновременно. Следовательно, все процессы выполняются через 3 секунды.

import subprocess

processes = []

p1 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p2 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)
p3 = subprocess.Popen("sleep 3", stdout=subprocess.PIPE, shell=True)

processes.append(p1)
processes.append(p2)
processes.append(p3)

for p in processes:
    if p.wait() != 0:
        print("There was an error")

print("all processed finished")

подпроцесс может быть до 2 раз медленнее, чем система ОС
MonsieurBeilto,

0

Я думаю, что process.communicate () подойдет для вывода небольшого размера. Для большей производительности это не лучший подход.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.