Как заставить Попена ждать, чтобы команда закончила? - PullRequest
0 голосов
/ 04 января 2019

Цель состоит в том, чтобы команда запускалась в оболочке bash с Popen, а затем выходные данные этой команды передаются в переменную, но Popen должен подождать, пока команда завершит свою работу, прежде чем двигаться дальше, чего не происходит.

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

var1 = Popen(["command | grep 'stuff' | cut -d 'delimiter' -f3"], 
             shell=True, stdout=PIPE,
             universal_newlines=True).communicate()[0].rstrip()
var2 = Popen(["command | grep 'stuff' | cut -d 'delimiter' -f1"], 
             shell=True, stdout=PIPE,
             universal_newlines=True).communicate()[0].rstrip()
print(var1 + var2)

Python правильно печатает var1, но не var2, что является None, потому что он не был назначен ничем, так как команда не выполнялась или не было времени для завершения. Выполнение команды var2 непосредственно на терминале, точно так же, как в программе на python, дает желаемые результаты, но когда python пытается запустить его, он просто пропускает его и печатает var1 и var2, но отображается только строка var1, var2 полностью игнорироваться.

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Вы должны передать команду как строку или разобрать ее в токены самостоятельно. Вы захотите использовать subprocess.run вместо низкоуровневого Popen. Тривиально

var = subprocess.run("command | grep 'stuff' | cut -d 'delimiter' -f3", 
         shell=True, stdout=PIPE,
         universal_newlines=True).stdout

Гораздо лучшее решение - заменить grep и cut кодом Python и избавиться от shell=True в качестве полезного бонуса.

var = list()
output = subprocess.run(["command"], stdout=PIPE, universal_newlines=True)
for line in output.stdout.split('\n'):
    if 'stuff' in line:
        var.append(line.split('delimiter')[2])
0 голосов
/ 04 января 2019

Ошибка AttributeError: 'str' object has no attribute 'wait' возникает из-за того, что метод communicate() возвращает кортеж из (stdout, stderr) строк. wait() - это метод самого объекта Popen. Вам не нужно звонить на wait(), если вы используете communicate(), так как он будет ждать вас. И вы не можете вызвать wait() объекта Popen, если вы выбросите единственную ссылку на него.

Тем не менее, вам действительно нужно использовать grep и cut для выполнения работы? Что-то вроде этого, вероятно, будет быстрее и с меньшей вероятностью будет содержать ошибку безопасности:

p = Popen(['command'], stdout=PIPE, universal_newlines=True)
result = []
for line in p.stdout:
    if 'stuff' in line:
        value = line.split('delimiter')[4]
        result.append(value)
...