0

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

        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'))

由于 subprocess.Popen 对象不可腌制,因此无法将其作为会话变量放入,我想从进度类中获取 p.poll() 和 p.stdout.read() 。

此外,我希望代码可在 linux 和 windows 中运行,我在 windows 中设置了我的开发设置,并将其部署在 linux 服务器上。

有人可以在这里帮我吗...

谢谢你。

4

1 回答 1

0

我把它变成了一个 处理进程,并从生成的进程中为进程执行p.wait(),生成的进程负责其余的步骤并将结果更新到数据库中。

web.py 进度页面将在数据库中检查执行进度,从而解决。

代码:

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
于 2013-02-24T13:13:51.773 回答