如何使 Flask 应用程序每 5 分钟运行一次?

6

我有一个应用程序,目前已经按照预期运行,但现在我想让它每隔5分钟从一些虚拟机中抓取实时数据。在下面的代码中,我将其设置为每10秒更新一次,只是为了检查是否正常工作,但没有任何变化。我正在使用time.sleep。我还缺少什么?

import time
from flask import Flask, render_template
from testapi import grab_cpu

app = Flask(__name__)

starttime = time.time()
while True:

    machines =["build05", "build06", "build07","build08", "build09", "build10", "build11", "build12","build14","build15", "winbuild10","winbuild11", "winbuild12", "winbuild13", "wbuild14", "wbuild15", "winbuild16", "winbuild17", "winbuild18"] 

    cpu_percentage =[grab_cpu("build05"), grab_cpu("build06"),grab_cpu("build07"),  
            grab_cpu("build08"), grab_cpu("build09"), grab_cpu("build10"), grab_cpu("build11"), grab_cpu("build12"), grab_cpu("build13"), grab_cpu("build14"), grab_cpu("build15"), grab_cpu("winbuild10"), grab_cpu("winbuild11"), grab_cpu("winbuild12"), grab_cpu("winbuild14"), grab_cpu("winbuild15"), grab_cpu("winbuild16"), grab_cpu("winbuild17"), grab_cpu("winbuild18")] 

    @app.route("/")  # this sets the route to this page
    def home():
        return render_template('testdoc.html', len = len(machines), machines = machines, cpu_percentage = cpu_percentage)

    app.run(use_reloader = True, debug = True) 
    time.sleep(10.0 - ((time.time() - starttime) % 10.0))

编辑(这是一个带有建议的更新,但仍未按照我希望的方式工作): 更多信息:我有一个包含函数grab_cpu的文件,它进行api调用到虚拟机并返回使用率百分比。 我另外有一个名为test doc.html的文件,仅用于显示html。根据这些响应,我猜想需要使用一些 JavaScript 和套接字编程。请问能否提供指向正确方向的链接?

import time
from flask import Flask, render_template
from testapi import grab_cpu

app = Flask(__name__)



@app.route("/")  # this sets the route to this page
def home():
    starttime = time.time()

    while True:
        machines =["build05", "build06", "build07","build08", "build09", "build10", "build11", "build12","build14","build15", "winbuild10","winbuild11", "winbuild12", "winbuild13", "wbuild14", "wbuild15", "winbuild16", "winbuild17", "winbuild18"] 

        cpu_percentage =[grab_cpu("build05"), grab_cpu("build06"),grab_cpu("build07"),  
            grab_cpu("build08"), grab_cpu("build09"), grab_cpu("build10"), grab_cpu("build11"), grab_cpu("build12"), grab_cpu("build13"), grab_cpu("build14"), grab_cpu("build15"), grab_cpu("winbuild10"), grab_cpu("winbuild11"), grab_cpu("winbuild12"), grab_cpu("winbuild14"), grab_cpu("winbuild15"), grab_cpu("winbuild16"), grab_cpu("winbuild17"), grab_cpu("winbuild18")] 
        return render_template('testdoc.html', len = len(machines), machines = machines, cpu_percentage = cpu_percentage)
        time.sleep(10.0 - ((time.time() - starttime) % 10.0))
app.run(use_reloader = True, debug = True) 
    

这里是页面: 网站图片 谢谢。

3
不要这样做。将您的查询移至“home”路由内,并在Redis或类似缓存系统之后进行移动,以避免多次运行昂贵的操作。 - Adam Smith
2
我看不出你在使用任何公认的设计模式。1.拥有一个控制器进程,可以调用Flask应用程序中的RESTful API路由来更新缓存(例如Redis)。2.您的主页路由通过使用render_template从缓存获取数据来显示数据。3.如果您希望客户端浏览器以不同的频率刷新页面,请使用一些JS和setinterval()重新加载页面。 - Rob Raymond
@RobRaymond 我不认为我是。我只是两天前学习了 Flask。还在学习中。谢谢你的建议。 - Colorful Codes
@AdamSmith 你是说移动我的变量吗?哪种操作比较昂贵?我猜每次调用grab_cpu()都是。 - Colorful Codes
2个回答

3

我不建议使用 Flask 来处理调度。Flask 请求的预期流程如下:

  1. 从浏览器接收 HTTP 请求
  2. 尽快生成响应(理想情况下为几毫秒,但几乎总是在几秒内)
  3. 将响应返回给浏览器

上面代码的意图似乎是使用 Flask 向浏览器推送更新,但 Flask 只能响应接收到的请求,并不能强制浏览器改变。

对于你描述的用例,一个简单的解决方案是在浏览器中处理刷新逻辑。

下面是一个非常基本的示例,将此代码放入你的 testdoc.html 模板中:

<script type="text/javascript">
    setTimeout(function () { 
      location.reload();
    }, 10 * 1000);
</script>

这将使页面每10秒重新加载,从而生成一个新的请求到您的 Flask 服务器并在浏览器中显示更新的信息。

如果你想更加高端并且避免整个页面重新加载,你可以使用 JavaScript 的 XmlHttpRequests 或者更现代的 Fetch API 来异步更新页面的特定元素。

另外,这里是 Python 代码的建议简化:

from flask import Flask, render_template
from testapi import grab_cpu

app = Flask(__name__)

build_machines = list(map(lambda i: 'build%02d' % i, range(5, 16)))
win_build_machines = list(map(lambda i: 'winbuild%02d' % i, range(10, 19)))
machines = build_machines + win_build_machines

# Handle HTTP GET requests to / route
@app.route("/", methods=['GET'])
def home():
        cpu_percentage = list(map(lambda b: grab_cpu(b), machines))
        return render_template('testdoc.html', len = len(machines), machines = machines, cpu_percentage = cpu_percentage)

app.run(use_reloader = True, debug = True) 
    

我最终使用了除Flask之外的另一种方法来获得我想要的结果,但我很感谢这个解释。谢谢。 - Colorful Codes

2
您的代码需要一些改进,Flask视图不应该在循环内声明。我建议执行以下步骤:
  1. 将Flask视图移出while循环。
  2. 也将服务器声明在循环外。
  3. 将您的代码写入函数中。
  4. 仅通过调用函数运行while循环以从来源获取信息。
基于我认为这只是一个举例而已,我还会对您的要求做一些假设:
  • 这不是您的确切代码。
  • 您的代码完美地工作,但此实现缺乏某些内容。
  • 您的项目具有一定的复杂性。
  • 您需要在其他地方展示这些数据。
基于这些(和可能的其他条件),我认为您有两种方式可以有效地实现所需:
  1. (不推荐)创建Cron作业并在专用脚本中运行所有内容。
  2. (我最喜欢的)封装脚本逻辑并将其声明为Celery任务的Flask API调用、方法或函数,并安排每隔5秒运行一次,更新数据库,并使用带有一些JS反应性的视图实时显示数据。

我很困惑,为什么你不相信这是我的代码... - Colorful Codes
Python语法的基本错误让我认为这不是你的生产就绪代码 @ColorfulCodes - Sebastian Reyes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接