python web.py异步执行外部程序
我有一个web.py应用程序运行在内置的cherrypy服务器上。 我想在用户发布到url时执行一个外部脚本,该脚本将在python子流程的后台运行。Popen调用和web.py将重定向到另一个页面,其中使用jquery ajax请求监视脚本的进度。 但我无法在这里正确地实现这一点。 代码片段如下,如果需要,我可以提供更多信息python web.py异步执行外部程序,python,linux,web.py,Python,Linux,Web.py,我有一个web.py应用程序运行在内置的cherrypy服务器上。 我想在用户发布到url时执行一个外部脚本,该脚本将在python子流程的后台运行。Popen调用和web.py将重定向到另一个页面,其中使用jquery ajax请求监视脚本的进度。 但我无法在这里正确地实现这一点。 代码片段如下,如果需要,我可以提供更多信息 import web from multiprocessing import Process import subprocess, shl
import web
from multiprocessing import Process
import subprocess, shlex
import time, json
from login import authorize, sessidGen
def __callProcess(processString,mod='w',shell=False):
if not shell: args = shlex.split(processString)
else: args = processString
out = open('./bteq/logs/output.log',mod)
err = open('./bteq/logs/error.log',mod)
p = subprocess.Popen(args,stdout=out,stderr=err,shell=shell)
return p
def setExec():
__callProcess("chmod +x ./bteq/*.sh",shell=True)
def bteqExec(filename,system):
if system not in ['prod','da','cdw','cdw2','cert','']: return False
processString = " ".join([filename,system])
p = __callProcess(processString)
return p.pid
render = web.template.render('templates/',base='layout')
render_plain = web.template.render('templates/')
class Executor:
def GET(self):
authorize()
session = web.ctx.session
inputs = web.input(sessid={},type={})
if not inputs.sessid or session.id != inputs.sessid: web.seeother('/')
if inputs.sessid and inputs.type:
return render.executor('BTEQ Executor',inputs.type,inputs.sessid)
else: raise web.seeother('/')
def POST(self):
authorize()
session = web.ctx.session
inputs = web.input(sessid={},type={},act={})
if not inputs.sessid or session.id != inputs.sessid: web.seeother('/')
if inputs and inputs.act == 'start':
pid = bteqExec('python ./bteq/timer.py','')
session.id = sessidGen()
session.exctrpid = pid
return web.seeother('/progress.htm')
else: raise web.seeother('/')
class progress:
def GET(self):
authorize()
session = web.ctx.session
inputs = web.input(ajax={})
if inputs.ajax == 'true':
web.header('Content-Type', 'application/json')
if session.count >= 100: session.count = 0
session.count += 10
pid = session.exctrpid
out = open('./bteq/logs/output.log','r')
err = open('./bteq/logs/error.log','r')
output = ('<strong>OUTPUT:</strong><br>'+out.read()).replace('\n','<br>')
err = err.read()
if err:error = ('<strong>ERRORS:</strong><br>'+err.read()).replace('\n','<br>')
else: error = None
d = {'count':session.count,'msg':output,'err':error,'rc':pid,'session_id':session.session_id}
return json.dumps(d)
r = web.template.Template('$def with (title)\n$var title: $title\n')
return render_plain.layout_pgbar(r('progress test'))
导入web
从多处理导入进程
导入子流程,shlex
导入时间,json
从登录导入授权,sessiongen
def\uu callProcess(processString,mod='w',shell=False):
如果不是shell:args=shlex.split(processString)
else:args=processString
out=打开('./bteq/logs/output.log',mod)
err=open('./bteq/logs/error.log',mod)
p=subprocess.Popen(args,stdout=out,stderr=err,shell=shell)
返回p
def setExec():
__调用过程(“chmod+x./bteq/*.sh”,shell=True)
def bteqExec(文件名,系统):
如果系统不在['prod'、'da'、'cdw'、'cdw2'、'cert'、''中:返回False
processString=”“.join([文件名,系统])
p=\uuu调用进程(processString)
返回p.pid
render=web.template.render('templates/',base='layout')
render_plain=web.template.render('templates/'))
类别执行人:
def GET(自我):
授权
session=web.ctx.session
inputs=web.input(sessiond={},type={})
如果不是inputs.sessiond或session.id!=inputs.sessiond:web.seeother(“/”)
如果inputs.sessiond和inputs.type:
返回render.executor('BTEQ executor',inputs.type,inputs.sessiond)
其他:提升web。请参见其他(“/”)
def POST(自我):
授权
session=web.ctx.session
inputs=web.input(sessiond={},type={},act={})
如果不是inputs.sessiond或session.id!=inputs.sessiond:web.seeother(“/”)
如果inputs和inputs.act==“开始”:
pid=bteqExec('python./bteq/timer.py','')
session.id=sessiondGen()
session.exctrpid=pid
返回web.seeother('/progress.htm'))
其他:提升web。请参见其他(“/”)
课程进度:
def GET(自我):
授权
session=web.ctx.session
inputs=web.input(ajax={})
如果inputs.ajax==“true”:
web.header('Content-Type','application/json')
如果session.count>=100:session.count=0
session.count+=10
pid=session.exctrpid
out=open('./bteq/logs/output.log',r')
err=open('./bteq/logs/error.log',r')
输出=('输出:
'+out.read())。替换('\n','
'))
err=err.read()
如果err:error=('错误:
'+err.read())。替换('\n','
'))
其他:错误=无
d={'count':session.count,'msg':输出,'err':error,'rc':pid,'session\u id':session.session\u id}
返回json.dumps(d)
r=web.template.template('$def with(title)\n$var title:$title\n')
返回render\u plain.layout\u pgbar(r(“进度测试”))
由于subprocess.Popen对象不可pickle,因此无法将其作为会话变量放入,我希望从progress类中删除p.poll()和p.stdout.read()
另外,我希望代码在linux和windows中都能运行,我在windows中安装了开发程序,并将其部署在linux服务器上
有人能帮帮我吗
谢谢。我把它变成了一个多处理进程并对派生进程中的子进程执行p.wait(),派生进程负责其余步骤并将结果更新到数据库中
web.py进度页将在数据库中检查执行进度,从而解决问题
代码:
在实际应用程序中,我没有运行“python./bteq/timer.py”,而是运行Teradata bteq脚本。我制作了一个多处理包装器来调用子流程。这很好,但是,我想知道是否有一个正确的方法。
from multiprocessing import Process
class ProcHandler(Process):
def __init__(self, *args, **kwargs):
#Initialize
Process.__init__(self, *args, **kwargs)
def run(self):
p = bteqExec('python ./bteq/timer.py','')
rc = p.wait()
# do update the resulting to database. and make the web.py
# Progress class read from database entry made by this Process.
return