如何在Python中使用子进程模块(当外部程序保持运行时)动态实现输出。我想从中动态获取输出的外部程序是 ngrok , 只要我的程序正在运行,ngrok 就会继续运行,但我需要在进程运行时输出,以便我可以提取新生成的“转发 url”
当我尝试这样做时:
cmd = ['ngrok', 'http', '5000']
output = subprocess.Popen(cmd, stdout=subprocess.PIPE, buffersize=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 使用的 I/O 占用/限制,您可以使用 pty.fork()
并通过os.read
读取 child 的标准输出模块:
#!/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'))
会告诉你输出是什么。
关于python - python subprocess 模块的动态输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53229305/