python web.py异步执行外部程序

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

我有一个web.py应用程序运行在内置的cherrypy服务器上。 我想在用户发布到url时执行一个外部脚本,该脚本将在python子流程的后台运行。Popen调用和web.py将重定向到另一个页面,其中使用jquery ajax请求监视脚本的进度。 但我无法在这里正确地实现这一点。 代码片段如下,如果需要,我可以提供更多信息

        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