Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python子流程模块的动态输出_Python_Python 3.x_Subprocess_Ngrok - Fatal编程技术网

python子流程模块的动态输出

python子流程模块的动态输出,python,python-3.x,subprocess,ngrok,Python,Python 3.x,Subprocess,Ngrok,当外部程序在python中运行时,如何使用子流程模块动态实现输出。我想从中动态获取输出的外部程序是, 只要我的程序在运行,ngrok就会一直运行,但我需要在进程运行时输出,以便提取新生成的转发url 当我尝试这样做时: cmd = ['ngrok', 'http', '5000'] output = subprocess.Popen(cmd, stdout=subprocess.PIPE, buffersize=1) 它一直将输出存储在缓冲区中我知道这是一个副本,但我现在找不到任何与此相关的线

当外部程序在python中运行时,如何使用子流程模块动态实现输出。我想从中动态获取输出的外部程序是, 只要我的程序在运行,ngrok就会一直运行,但我需要在进程运行时输出,以便提取新生成的转发url

当我尝试这样做时:

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

它一直将输出存储在缓冲区中

我知道这是一个副本,但我现在找不到任何与此相关的线程。我得到的只是输出。交流

下面是一个可能有用的片段:

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.

poll检查进程是否有退出代码。如果进程已死亡,则继续循环并打印进程标准输出中的任何内容

还有其他更好的方法,但这是我能给你的最低限度,不会很快变得复杂

例如,process.stdout.read可以与select.select结合使用,以在新行不足时实现更好的缓冲输出。因为如果\n从未出现,上述示例可能会挂起整个应用程序

这里有很多缓冲区陷阱,在进行类似这样的手动操作之前,您需要了解这些陷阱。否则,请改用process.communicate

编辑:为了绕过ngrok使用的I/O的限制,您可以使用pty.fork并通过os.read模块读取child的标准输出:

这里仍然有一个问题,我不太清楚这是什么或为什么。 我猜这个过程正在等待一个信号/刷新一些。 问题是,它只打印ncurses的第一个设置数据,这意味着它会擦除屏幕并设置背景色


但这至少会给你这个过程的输出。替换printoutput.decode'UTF-8'将向您显示该输出是什么。

看起来程序卡在这一行代码中process=subprocess.Popencmd,stdout=subprocess.PIPE,stderr=subprocess.stdout到达这一行后,程序开始将输出存储在缓冲区中并保持沉默。。当ngrok运行时,我想从ngrok中提取的唯一内容是ngrok提供的向前的urlprovides@arslanmughal你部分正确,它没有卡在Popen线tho上。它卡在printprocess.stdout.readline上。这是一个巨大的不同,因为它告诉我们Popen无法从进程中获得输出。我还尝试了stdout.read1,它不返回任何内容。所以我增加了一个额外的获取输出的方法。可能是重复的。虽然这只是问题本身,但它不适用于ngrok或其他ncurses应用程序。所以,把这个留给其他人,他们最终想知道如何从子流程中获得输出。
#!/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()