Я знаю, что это дубликат, но сейчас я не могу найти соответствующие темы по этому поводу. Все, что я получаю, это 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'))
покажет вам, что это за выход.