是否可以将python子流程的输出实时流式传输到网页?
提前感谢您的帮助。我对python相当陌生,甚至对html也比较陌生 过去几天我一直在尝试创建一个带有按钮的网页,以便在家庭服务器上执行任务 目前,我有一个python脚本,它生成了一个带有按钮的页面:是否可以将python子流程的输出实时流式传输到网页?,python,html,linux,web,cgi,Python,Html,Linux,Web,Cgi,提前感谢您的帮助。我对python相当陌生,甚至对html也比较陌生 过去几天我一直在尝试创建一个带有按钮的网页,以便在家庭服务器上执行任务 目前,我有一个python脚本,它生成了一个带有按钮的页面: (See the simplified example below. removed code to clean up post) 然后,运行所述命令并输出到页面上的iframe的python脚本: (See the simplified example below. removed code
(See the simplified example below. removed code to clean up post)
然后,运行所述命令并输出到页面上的iframe
的python脚本:
(See the simplified example below. removed code to clean up post)
这会在命令完成后输出整个完成的输出。我还尝试将-u
选项添加到python脚本中,以无缓冲地运行它。我还尝试过使用Python子流程
。如果有帮助,我正在运行的命令类型有apt get update
,以及其他用于移动文件和修复文件夹权限的Python脚本
当从普通的Ubuntu服务器终端运行时,它运行良好,实时输出,根据我的研究,它应该在命令运行时输出
谁能告诉我哪里出了问题?我应该使用不同的语言来执行此功能吗
编辑简化示例:
首页:
#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>
这就是它的工作原理吗
编辑日期:2014年3月19日:
我使用Imrans方式运行的任何bash/shell命令似乎都能以近乎实时的方式输出到iframe。但是如果我通过它运行任何类型的python脚本,那么输出将被缓冲,然后发送到iframe
我是否可能需要通过管道传输由运行web服务器的脚本运行的python脚本的输出?您需要使用管道传输未缓冲的命令行输出。”s wsgiserver模块内置了对分块传输编码的支持。WSGI应用程序可以是返回字符串列表的函数,也可以是生成字符串的生成器。如果将生成器用作WSGI应用程序,CherryPy将自动使用分块传输
让我们假设这是一个程序,它的输出将被流式传输
# 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()
这是我们的网络服务器
2014版(较旧的cherrpy版)
2018版
使用pythonwebapp.py
启动服务器,然后在另一个终端中使用curl
发出请求,并观察逐行打印的输出
对这是一个看起来令人困惑的问题。对我来说,它看起来像是向终端发送命令并在那里显示?。我想要的是在iframe中显示命令的输出,就像它在终端中显示一样@J.F.Sebastiany您的情况比代码示例更简单,在代码示例中,消息在浏览器中的
javascript
代码和服务器上的子进程之间来回发送。回答您的问题:子进程的标准输出被发送到浏览器。是的,在命令完成后,使用我的代码,iframe将填充命令的整个输出。我希望它能像您在终端中运行命令时看到的那样,填充每一行。但我不知道怎么做@J.F.Sebastian会在子进程刷新其内部标准输出缓冲区后立即发送输出(示例python程序使用-u
标志,因此没有缓冲区;每个字节都会立即发送)。抱歉,正如我所说,我对这一点还不太熟悉,所以我对这一点一无所知。我在ubuntu服务器13.10上使用apache作为我的web服务器。使用您的代码或类似代码,是否会将该输出作为按钮输出到同一页面上的iframe?就像在click button=>runs subprocess on server=>iframe中一样,当它发生时,是否用输出填充@如果您不必运行Apache,这个脚本本身就是一个web服务器。如果正在运行此命令,可以使用要作为querystring执行的命令将iframe['src']=''设置为querystring,并将querystring从应用程序代码中的'environ'中解析出来。只是为了澄清一下,我正在运行apache,因为我正在服务器上托管一个基本网站。我试图创建一个带有一些按钮的页面,这些按钮运行特定的任务(比如apt get update)并在iframe中逐行输出。而不是在命令完成后。有没有一种方法可以用apache实现这一点@imran当我在终端中运行您的示例时,我得到的输出就像我在终端中键入命令一样,我希望该输出显示在iframe中,就像命令在终端中运行一样。对不起,如果我听起来很困惑@Imran刚刚尝试了您的示例,打开了ip:8000的浏览器,它准确地显示了我想要的卓越。现在我如何使用apache和iframe来实现这一点?谢谢@伊姆兰
# 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()
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.
# slowprint.py
import sys
import time
for i in xrange(5):
print i
sys.stdout.flush()
time.sleep(1)
# 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()
#!/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())
curl 'http://localhost:8000'