Python中的非消息队列/简单长轮询(和Flask)

时间:2012-06-22 14:25:11

标签: python flask long-polling

我正在寻找一种简单的方法(即,不需要我设置单独的服务器来处理消息传递队列)的方法来对运行计算并生成图形的小型Web界面进行长轮询。这就是我的网络界面需要做的事情:

  1. 用户在网络界面中请求图表/数据
  2. 服务器运行一些计算。
  3. 当服务器正在运行计算时,一个小容器会更新(可能通过AJAX / jQuery)计算进度(类似于你在带打印的consol中所做的那样)(即打印'计算密度函数......' ))
  4. 计算完成并向用户显示图表。
  5. 由于计算都在服务器端完成,我不确定如何轻松设置它。显然,我想设置一个REST API来处理轮询,这在Flask中很容易。但是,我不确定如何检索实际更新。显而易见的是,虽然这个目的很复杂,但解决方案是设置消息传递队列并进行一些长轮询。但是,我不确定这是否是这种简单方法的正确方法。

    以下是我的问题:

    1. 有没有办法使用文件系统执行此操作?性能不是一个大问题。 AJAX / jQuery可以从文件中查找消息吗?将进度保存到某个.json文件?
    2. 酸洗怎么样? (我对酸洗并不是很了解,但也许我可以腌制消息字典,并且可以通过处理轮询的API读取它。)
    3. 投票甚至是正确的方法吗?是否有更好或更常见的模式来处理这个问题?
    4. 我有一种感觉我过于复杂,因为我知道这种事情在网络上很常见。我经常看到发生的事情,并且在进行一些计算时会运行一些“loading.gif”图像(例如,在Google Analytics中)。

      感谢您的帮助!

2 个答案:

答案 0 :(得分:41)

我使用Flask和jQuery构建了几个这样的应用程序。根据这些经验,我会说你的计划很好。

  1. 不要使用文件系统。您将遇到JavaScript安全问题/保护。在不太可能的情况下,您找到合理的解决方法,您仍然没有任何可移植或可扩展的东西。相反,使用一个小的本地Web服务框架,如Flask。

  2. 不要泡菜。使用JSON。它是Web应用程序和REST接口的语言。 jQuery和那些用于绘制图表,图形等的基于jQuery的好插件将需要JSON。它易于使用,易于阅读,对于小规模的应用程序,没有理由去任何其他地方。

  3. 长轮询适用于您想要完成的任务。纯基于HTTP的应用程序有一些限制。而像Socket.IO这样的WebSockets和类似的socket-ish层就是未来。但是,根据我的经验,找到好的,简单的服务器端实现示例一直很困难。我看起来很努力。有很多示例要求您设置Node.js,REDIS和其他中间件。但为什么我们要设置两个或三个独立的中间件服务器?真是荒唐可笑。因此,对像Flask这样简单,纯粹的Python Web框架进行长时间轮询是进入IMO的方法。

  4. 代码不仅仅是一个代码段,因此我在a Mercurial repository on bitbucket中添加了一个简单的示例,而不是将其包含在内,您可以自由查看,复制或克隆。有三个部分:

    • serve.py基于Python / Flask的服务器
    • templates/index.html 98%HTML,2%模板文件,基于Flask的服务器将呈现为HTML
    • static/lpoll.js基于jQuery的客户端

答案 1 :(得分:10)

长时间轮询是一种合理的解决方法,之前对大多数浏览器提供简单,自然的Web套接字支持,并且在它与Flask应用程序一起轻松集成之前。但是在2013年中期,Web Socket支持已经走过了漫长的道路。

Here is an example,类似于上面的那个,但是集成了Flask和Web Sockets。它运行在geventgevent-websocket的服务器组件上。

请注意,此示例并非旨在成为Web Socket杰作。它保留了很多lpoll结构,使它们更容易比较。但它立即提高了Web应用程序的响应能力,服务器开销和交互性。

Python 3.7 +的更新

自最初回答5年以来,WebSocket变得更容易实现。从Python 3.7开始,异步操作已经成熟为主流实用性。 Python Web应用程序是完美的用例。他们现在可以像JavaScript和Node.js一样使用异步,留下了“并发性”的一些怪癖和复杂性。特别是,请查看Quart。它保留了Flask的API以及与许多Flask扩展的兼容性,但是启用了异步。一个关键的副作用是WebSocket连接可以与HTTP连接并行地优雅地处理。 E.g:

from quart import Quart, websocket

app = Quart(__name__)

@app.route('/')
async def hello():
    return 'hello'

@app.websocket('/ws')
async def ws():
    while True:
        await websocket.send('hello')

app.run()

Quart只是升级到Python 3.7的众多重要原因之一。