如何运行外部程序并在Cherrypy中报告浏览器asyn

时间:2016-03-17 13:56:38

标签: python websocket cherrypy server-sent-events

我正在尝试使用Cherrypy后端设置一个Web应用程序。 Web应用程序只是一个程序的GUI,它将在服务器中运行,解析一些文件。我希望能够做的是上传文件,并在后端执行程序,将流程的输出报告回浏览器。

我已经使用Cherrypy服务器设置了CORS和Server发送的事件。我不确定这是服务器发送事件还是WebSockets的情况。我真的在寻找一种方法来有效地实现这个功能(报告回来),并能够为多个客户提供服务(已经支持了)。

我尝试过:

  • 设置SSE事件,该事件发送保存子进程输出的变量(public)。这适用于单个客户端。由于对象属性在cherrypy中持久存在。 (涵盖在此question)。
  • 然后我尝试做会话。这是我被卡住的地方,会话元素集在SSE函数中消失。我尝试了很多东西,但没有成功。 即使它们是,我也不确定如何避免SSE请求之间的共享数据。

SSE方法:

@cherrypy.expose
def getUpdate(self, _=None):

    print "Horay! %s" % cherrypy.session.get('pid') # <-- this is None, even though its set in the main method
    try:
        cherrypy.session['youknow'] = "iknow"
        cherrypy.session.save()
    except Exception as e:
        raise e
    if _:
        data = 'data: meh meh...\n\n'
        return data
    else:
        def content(data=None):

            if self.dataReady and self.prog_output is not None:
                response = ""
                for output in self.prog_output:
                    response += 'data: %s \n\n' % str(output)
                data = 'retry: 2000\n%s \n\n' % response
                return data
            elif self.dataFinished:
                self.dataFinished = False
                return 'data: + Done\n\n'

        return content()

getUpdate._cp_config = {'response.stream': True, 'tools.encode.encoding': 'utf-8'}

主要方法:

@cherrypy.expose
@cherrypy.tools.noBodyProcess()
def uploadFile(self, file=None):

    theFile = file

    # Save the pid in the user's session (a thread-safe place)
    cherrypy.session['pid'] = "pid"
    cherrypy.session.save()

    // calls the external program and parses here in a different thread, which updates the prog_output variable

Cherrypy Config:

if __name__ == '__main__':
    cherrypy.tools.CORS = cherrypy._cptools.HandlerTool(CORS)
    cherrypy.config.update({
    "tools.CORS.on": True,
    "server.socket_port": 8090,
    "server.thread_pool": 8,
    "tools.sessions.on": True,
    # 'tools.sessions.storage_type': "File",
    # 'tools.sessions.storage_path': 'sessions',
    # 'tools.sessions.locking': 'explicit',

这只是解决会话问题的一种情况,还是我应该在这个特定的用例中使用WebSockets。

1 个答案:

答案 0 :(得分:0)

通过将问题分解为两部分,我能够解决这个问题(不久前)。

  • 首先,我上传了需要处理的文件。然后,服务器返回这些文件路径和新文件的名称作为响应。
  • 一旦我从服务器获得响应(filepaths,newfilename),我就会调用服务器上的SSE事件函数(即www.server.com/runProc/filepath/filepath2/newfilepath),该函数运行该过程并流式传输输出回浏览器。

我的问题是我试图一次性做到这一点,这反过来又造成了一个不必要的问题。此外,通过这种方式,不需要跨多个请求进行会话或保存数据。