Команда Python popen. Зачекайте, поки команда не буде закінчена


79

У мене є скрипт, де я запускаю команду оболонки popen. Проблема полягає в тому, що скрипт не чекає, поки ця команда 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.
Чанг

підпроцес може бути вдвічі повільнішим, ніж система os - bugs.python.org/issue37790
MonsieurBeilto

subprocess.run()було додано в Python 3.5 і є "Рекомендованим підходом до виклику підпроцесів"
LoMaPh

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

підпроцес може бути вдвічі повільнішим, ніж система os - bugs.python.org/issue37790
MonsieurBeilto

12

Примусово popenне продовжувати, поки не буде прочитано всі вихідні дані, виконавши:

os.popen(command).read()

2
Я не фахівець з python, але це, здається, найпростіше рішення, яке вносить найменші зміни в оригінальний код. Будь-яка причина, чому це не буде хорошим рішенням?
jdmcnair

7

Нехай буде командою, яку ви намагаєтесь передати

os.system('x')

тоді ви приховуєте це до заяви

t = os.system('x')

тепер python буде чекати результату з командного рядка, щоб його можна було призначити змінній 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' У чому проблема? Знову дякую.
michele

12
Ви не натиснули посилання, яке я надав. waitє методом subprocessкласу.
Олів'є Вердьє

1
wait може
зайти в

підпроцес може бути вдвічі повільнішим, ніж система os - bugs.python.org/issue37790
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")

підпроцес може бути вдвічі повільнішим, ніж система os - bugs.python.org/issue37790
MonsieurBeilto

0

Я думаю, що process.communicate () був би придатним для вихідних даних із невеликим розміром. Для більшої продукції це був би не найкращий підхід.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.