Динамический вывод из модуля подпроцесса Python

как я могу добиться вывода динамически с помощью модуля подпроцесса (пока внешняя программа продолжает работать) в python. Внешняя программа, из которой я хочу получать динамический вывод, - нгрок, ngrok продолжает работать, пока работает моя программа, но мне нужен вывод во время выполнения процесса, чтобы я мог извлечь вновь сгенерированный «URL-адрес пересылки»

когда я пытаюсь сделать:

cmd = ['ngrok', 'http', '5000']
output = subprocess.Popen(cmd, stdout=subprocess.PIPE, buffersize=1)

он продолжает хранить вывод в буферах

Возможный дубликат Вывод на печать в реальном времени из подпроцесса. Хотя это просто вопрос, но он не будет работать для ngrok или другого приложения ncurses. Так что просто оставим это здесь для других, которые в конечном итоге здесь задаются вопросом, как получить вывод с subprocess.

Torxed 10.11.2018 10:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
1 277
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я знаю, что это дубликат, но сейчас я не могу найти подходящих тем по этому поводу. Все, что я получаю, это output.communicate().

Вот фрагмент, который может быть полезен:

import subprocess
cmd = ['ngrok', 'http', '5000']
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

while process.poll() is None:
    print(process.stdout.readline())
print(process.stdout.read())
process.stdout.close()

Это выведет все, что выводит процесс, через ваш скрипт на ваш вывод. Это делается путем поиска символа новой строки перед выводом.

Этот фрагмент кода работал бы, если бы не тот факт, что ngrok использует ncurses и / или передает вывод своему собственному пользователю / потоку, как когда SSH запрашивает пароль, когда вы выполняете ssh user@host.

process.poll() проверяет, есть ли у процесса код выхода (если он мертв), если нет, он продолжает цикл и печатает что-либо из stdout процесса.

Есть и другие (лучшие) способы сделать это, но это тот минимум, который я могу вам дать, чтобы он не усложнялся очень быстро.

Например, process.stdout.read() можно было бы использовать вместе с select.select() для достижения лучшего буферизованного вывода там, где новые строки пугают. Потому что, если \n так и не появится, в приведенном выше примере может зависнуть все ваше приложение.

Здесь много буферов-ловушек, о которых вам нужно знать, прежде чем делать подобные вещи вручную. В противном случае используйте process.communicate().

Обновлено: чтобы обойти ограничение / ограничение ввода-вывода, используемое ngrok, вы можете использовать pty.fork() и читать дочерний стандартный вывод через модуль os.read:

#!/usr/bin/python

## Requires: Linux
## Does not require: Pexpect

import pty, os
from os import fork, waitpid, execv, read, write, kill

def pid_exists(pid):
    """Check whether pid exists in the current process table."""
    if pid < 0:
        return False
    try:
        kill(pid, 0)
    except (OSError, e):
        return e.errno == errno.EPERMRM
    else:
        return True

class exec():
    def __init__(self):
        self.run()

    def run(self):
        command = [
                '/usr/bin/ngrok',
                'http',
                '5000'
        ]

        # PID = 0 for child, and the PID of the child for the parent    
        pid, child_fd = pty.fork()

        if not pid: # Child process
            # Replace child process with our SSH process
            execv(command[0], command)

        while True:
            output = read(child_fd, 1024)
            print(output.decode('UTF-8'))
            lower = output.lower()

            # example input (if needed)
            if b'password:' in lower:
                write(child_fd, b'some response\n')
        waitpid(pid, 0)

exec()

Здесь все еще есть проблема, и я не совсем понимаю, что это и почему. Я предполагаю, что процесс как-то ждет сигнала / флеша. Проблема в том, что он печатает только первые «установочные данные» ncurses, то есть стирает экран и устанавливает цвет фона.

Но это, по крайней мере, даст вам результат процесса. замена print(output.decode('UTF-8')) покажет вам, что это за результат.

похоже, что программа застряла на этой строке кода "" "process = subprocess.Popen (cmd, stdout = subprocess.PIPE, stderr = subprocess.STDOUT)" "" после достижения этой строки программа начинает сохранять вывод в буферах и замолкает .. единственное, что я хочу извлечь из ngrok во время работы ngrok, - это перенаправленный URL-адрес, который предоставляет ngrok

arslanmughal 10.11.2018 05:35

@arslanmughal Вы частично правы, он не застрял в строке Popen(). Он застрял на print(process.stdout.readline()). Это большая разница, потому что это просто говорит нам, что Popen() не может получить результат процесса. Я также пробовал stdout.read(1), который ничего не возвращает. Поэтому я добавил дополнительный способ получения вывода.

Torxed 10.11.2018 10:07

Другие вопросы по теме