是否可以将python子进程的输出实时流式传输到网页? [英] Is it possible to stream output from a python subprocess to a webpage in real time?

查看:85
本文介绍了是否可以将python子进程的输出实时流式传输到网页?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此先感谢您的帮助.我是python的新手,甚至是html的新手.

Thanks in advance for any help. I am fairly new to python and even newer to html.

最近几天,我一直在尝试创建一个带有按钮的网页,以便在家用服务器上执行任务.

I have been trying the last few days to create a web page with buttons to perform tasks on a home server.

目前,我有一个python脚本,可生成带有按钮的页面:

At the moment I have a python script that generates a page with buttons:

(See the simplified example below. removed code to clean up post)

然后是一个运行上述命令并输出到页面上的iframe的python脚本:

Then a python script which runs said command and outputs to an iframe on the page:

(See the simplified example below. removed code to clean up post)

在命令完成后,它会输出全部完成的输出.我还尝试将-u选项添加到python脚本以使其不带缓冲地运行.我也尝试过使用Python subprocess.如果有帮助,我正在运行的命令类型为apt-get update,以及用于移动文件和修复文件夹权限的其他Python脚本.

This does output the entire finished output after the command is finished. I have also tried adding the -u option to the python script to run it unbuffered. I have also tried using the Python subprocess as well. If it helps the types of commands I am running are apt-get update, and other Python scripts for moving files and fixing folder permissions.

从正常的Ubuntu服务器终端运行时,它可以正常运行并实时输出,根据我的研究,它应该在命令运行时输出.

And when run from normal Ubuntu server terminal it runs fine and outputs in real time and from my research it should be outputting as the command is run.

谁能告诉我我要去哪里错了?我应该使用其他语言来执行此功能吗?

Can anyone tell me where I am going wrong? Should I be using a different language to perform this function?

EDIT简化示例:

初始页面:

#runcmd.html

<head>
    <title>Admin Tasks</title>
</head>

<center>
<iframe src="/scripts/python/test/createbutton.py" width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true"></iframe>
<iframe width="650" height="800" frameborder="0" ALLOWTRANSPARENCY="true" name="display"></iframe> 
</center>

创建按钮的脚本:

cmd_page = '<form action="/scripts/python/test/runcmd.py" method="post" target="display" >' + '<label for="run_update">run updates</label><br>' + '<input align="Left" type="submit" value="runupdate" name="update" title="run_update">' + "</form><br>" + "\n"

print ("Content-type: text/html")
print ''
print cmd_page

应运行命令的脚本:

# runcmd.py:

import os 
import pexpect
import cgi
import cgitb
import sys 

cgitb.enable()

fs = cgi.FieldStorage()

sc_command = fs.getvalue("update")

if sc_command == "runupdate":
    cmd = "/usr/bin/sudo apt-get update"

pd = pexpect.spawn(cmd, timeout=None, logfile=sys.stdout)

print ("Content-type: text/html")
print ''
print "<pre>"

line = pd.readline()  
while line:
    line = pd.readline()

我还没有测试过上面的简化示例,所以不确定其功能是否正常.

I havent tested the above simplified example so unsure if its functional.

简化的示例现在应该可以使用.

Simplified example should work now.

如果我打开浏览器到ip:8000,则下面的伊朗代码,它显示的输出就像在终端中运行的一样,正是我想要的.除了我的网站使用Apache服务器和iframe来显示输出.我该如何使用Apache?

Imrans code below if I open a browser to the ip:8000 it displays the output just like it was running in a terminal which is Exactly what I want. Except I am using Apache server for my website and an iframe to display the output. How do I do that with Apache?

我现在使用下面的Imrans示例将输出传递到iframe,但是例如,它仍然可以缓冲:

I now have the output going to the iframe using Imrans example below but it still seems to buffer for example:

If I have it (the script through the web server using curl ip:8000) run apt-get update in terminal it runs fine but when outputting to the web page it seems to buffer a couple of lines => output => buffer => ouput till the command is done.

But running other python scripts the same way buffer then output everything at once even with the -u flag. While again in terminal running curl ip:800 outputs like normal.

这就是它应该如何工作的吗?

Is that just how it is supposed to work?

编辑19-03-2014:

EDIT 19-03-2014:

我使用Imrans方式运行的任何bash/shell命令似乎都几乎实时输出到iframe.但是,如果我通过它运行任何类型的python脚本,则输出将被缓冲,然后发送到iframe.

any bash / shell command I run using Imrans way seems to output to the iframe in near realtime. But if I run any kind of python script through it the output is buffered then sent to the iframe.

是否可能需要将运行Web服务器的脚本运行的python脚本的输出插入PIPE?

Do I possibly need to PIPE the output of the python script that is run by the script that runs the web server?

推荐答案

您需要使用 HTTP分块传输编码以流式传输未缓冲的命令行输出. CherryPy 的wsgiserver模块内置了对分块传输编码的支持. WSGI应用程序可以是返回字符串列表的函数,也可以是产生字符串的生成器.如果将生成器用作WSGI应用程序,CherryPy将自动使用分块传输.

You need to use HTTP chunked transfer encoding to stream unbuffered command line output. CherryPy's wsgiserver module has built-in support for chunked transfer encoding. WSGI applications can be either functions that return list of strings, or generators that produces strings. If you use a generator as WSGI application, CherryPy will use chunked transfer automatically.

让我们假设这是一个程序,其输出将被流式传输.

Let's assume this is the program, of which the output will be streamed.

# slowprint.py

import sys
import time

for i in xrange(5):
    print i
    sys.stdout.flush()
    time.sleep(1)

这是我们的Web服务器.

This is our web server.

# webserver.py

import subprocess
from cherrypy import wsgiserver


def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    proc = subprocess.Popen(['python', 'slowprint.py'], stdout=subprocess.PIPE)

    line = proc.stdout.readline()
    while line:
        yield line
        line = proc.stdout.readline()


server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 8000), application)
server.start()

2018版本

#!/usr/bin/env python2
# webserver.py
import subprocess
import cherrypy

class Root(object):
    def index(self):
        def content():
            proc = subprocess.Popen(['python', 'slowprint.py'], stdout=subprocess.PIPE)
            line = proc.stdout.readline()
            while line:
                yield line
                line = proc.stdout.readline()
        return content()
    index.exposed = True
    index._cp_config = {'response.stream': True}

cherrypy.quickstart(Root())

使用python webapp.py启动服务器,然后在另一个终端中使用curl进行请求,并观察一行一行打印输出

Start the server with python webapp.py, then in another terminal make a request with curl, and watch output being printed line by line

curl 'http://localhost:8000'

这篇关于是否可以将python子进程的输出实时流式传输到网页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆