Python Flask与APScheduler构建简易任务监控

1. Flask Web

Flask诞生于2010年,是用Python语言,基于Werkzeug工具箱编写的轻量级、灵活的Web开发框架,非常适合初学者或小型到中型的 Web 项目。

Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login),都需要用第三方的扩展来实现。其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。这两个也是Flask框架的核心。

Python最出名的框架要数Django,此外还有Flask、Tornado等框架。虽然Flask不是最出名的框架,但是Flask应该算是最灵活的框架之一,这也是Flask受到广大开发者喜爱的原因。

1.1. 安装 Flask

bash 复制代码
pip install flask

1.2. Flask框架结构

1.2.1. 路由route

路由是Web应用中访问不同页面的方式。在Flask中,我们可以通过定义不同的路由来实现不同页面的访问。

处理函数和和URL的关系,Flask通过修饰器把函数注册为路由。访问http://localhost:5000就会调用index这个视图函数

访问:http://127.0.0.1:5000,页面即可得到hello world.

在app对象上定义路由的方式如下:

python 复制代码
@app.route('/')

def index():
	return 'Hello World!'

这个路由将会匹配根目录,并返回一个"Hello World!"的字符串。

变量规则

要给URL添加变量部分,可以把特殊字段标记为<variable_name>,这部分将会作为命令参数传递到函数。

构造URL

在Web程序中常常需要获取某个页面的URL,在Flask中需要使用url_for('方法名')来构造对应方法的URL。

1.2.3. 模板

模板是Web应用中将数据呈现给用户的一种方式。在Flask中,我使用Jinja2模板引擎来渲染模板。

Jinja2 是一个 Python 模板引擎,主要用于在应用程序中生成动态内容。它由 Armin Ronacher 创建,是 Flask Web 框架默认使用的模板引擎,也广泛用于其他 Python Web 框架和项目中。

Flask默认使用Jinja2作为模板,Flask会自动配置Jinja 模板,默认情况下,模板文件需要放在templates文件夹下。

Jinja 模板和其他语言和框架的模板类似,都是通过语法将HTML文件中的特定元素替换为实际的值。类似java的JSP等模板。从下面的例子中我们应该可以看到Jinja 模板的基本语法了。代码块需要包含在{% %}块中。

使用 Jinja 模板,只需要使用render_template函数并传入模板文件名和参数名即可。

1.2.4. 运行

在 Flask 中,app.run() 方法用于运行应用的开发服务器。默认情况下,app.run() 使用的是 Werkzeug 服务器,并且只会在本地主机(127.0.0.1)上监听端口 5000。具体的默认参数如下:

python 复制代码
app.run(
    host="127.0.0.1",  # 监听的主机地址
    port=5000,          # 监听的端口号
    debug=False,        # 是否启用调试模式
    load_dotenv=True,   # 是否加载 .env 文件
    **options           # 其他选项,例如 ssl_context 等
)

如果你在应用的代码中只是简单地调用 app.run() 而没有传递参数,那么默认情况下应用会在本地主机的端口 5000 上运行,并且不启用调试模式。这通常用于在开发阶段进行测试和调试。

1.3. 创建 Flask 应用

1.3.1. 快速入门

创建一个 Python 文件(例如 app.py)来定义你的 Flask 应用:

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello, Flask!'

在这个例子中,我们创建了一个名为 app 的 Flask 应用,并定义了一个简单的路由 /,该路由返回 "Hello, Flask!"。

运行 Flask 应用

在命令行中运行以下命令启动 Flask 应用:

bash 复制代码
python app.py

你将看到输出类似于以下内容:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Flask 应用默认在 http://127.0.0.1:5000/ 上运行。在浏览器中打开这个地址,你将看到 "Hello, Flask!"。

1.3.2. 创建更复杂的路由和模板

以Flask与APScheduler构建简易任务监控应用为例,创建更多复杂的路由,并使用模板引擎(例如 Jinja2)来渲染 HTML 页面。以下是一个简单的示例:

1.3.2.1. 应用程序
python 复制代码
import pytz

from apscheduler.schedulers.background import BackgroundScheduler
import datetime

import sys
import os
from flask import Flask, render_template
from loguru import logger
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))

from PVSystem.PVAPScheduler import get_weather_data as get_weather24_data
from PVSystem.PVAPScheduler import monitor_data
from PVSystem.qweatherToDB import get_weather_data
from PVSystem.PVPowerForecastToDB import get_power_data
from PVSystem.PVForecastAPScheduler import set_pv_forecast
from PVSystem.PVTrainAPScheduler import get_weather_data as get_now_weather


logger.add("PVAPScheduler_{time}.log")

hms_dict = [{'fun':get_weather24_data,'id':'get_weather24_data','hour':None,'minute':'00','second':'20','trigger':'cron'},
            {'fun':monitor_data,'id':'monitor_data','hour':None,'minute':'00','second':'40','trigger':'cron'},
            {'fun':get_weather_data,'id':'get_weather_data','hour':'00','minute':'10','second':'00','trigger':'cron'},
            {'fun':set_pv_forecast,'id':'set_pv_forecast','hour':'00','minute':'13','second':'30','trigger':'cron'},
            {'fun':get_power_data,'id':'get_power_data','hour':'00','minute':'15','second':'00','trigger':'cron'},
            {'fun':get_now_weather,'id':'get_now_weather','hour':None,'minute':'05','second':'00','trigger':'cron'},]

app = Flask(__name__)

scheduler = BackgroundScheduler(timezone=pytz.timezone("Asia/Shanghai") )

@app.route('/')
def home():
    return 'Hello, Flask!'

@app.route('/task_list')
def task_list():
    jobs = scheduler.get_jobs()
    return render_template('task_list.html', jobs=jobs)

if __name__ == "__main__":
    # 添加任务到调度器
    for v in hms_dict:
        scheduler.add_job(v['fun'], v['trigger'],hour=v['hour'],minute = v['minute'], second=v['second'], misfire_grace_time=120,id=v['id'])

    # 启动 Flask 应用和调度器
    try:
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        pass

    # 启动 Flask 应用
    app.run(port=5002)

在这个例子中,我们定义了一个路由 /task_list,并使用 render_template 渲染一个包含参数的 HTML 页面。

1.3.2.2. 创建模板文件

在项目的根目录下创建一个名为 templates 的文件夹,并在其中创建模板文件,例如 task_list.html

html 复制代码
<!-- templates/task_list.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Task List</title>
	
    <style>
        table {
            width: 50%;
            border-collapse: collapse;
            margin-top: 20px;
        }

        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }

        th {
            background-color: #f2f2f2;
        }
    </style>	
	
</head>
<body>
    <h1>Task List</h1>

    <table>
        <thead>
            <tr>
                <th>任务名称</th>
                <th>下次开始执行时间</th>
            </tr>
        </thead>
        <tbody>
            {% for job in jobs %}
                <tr>
                    <td>{{ job.id }}</td>
                    <td>{{ job.next_run_time }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>	
</body>
</html>

这是一个简单的 HTML 模板,在这个模板中,我们使用 Jinja2 模板引擎来循环显示任务列表中的任务 ID 和下次运行时间,使用了 Jinja2 的模板语法。

1.3.2.3. 运行应用并访问路由

重新运行应用:

bash 复制代码
python app.py

在浏览器中访问 `http://127.0.0.1:5002/task_list。

这只是一个 Flask Web 开发的简单入门,Flask 提供了更多功能,例如数据库集成、表单处理、用户认证等,可以根据项目需求逐步学习和使用。

1.3.3. 应用部署

使用 WSGI(Web Server Gateway Interface)服务器是在生产环境中部署 Flask 应用的推荐做法。WSGI 是一种标准的接口,用于定义 Web 服务器和 Python Web 应用程序之间的通信协议。通过使用专业的 WSGI 服务器,可以提高性能、可靠性和安全性。

安装 Gunicorn

bash 复制代码
pip install gunicorn

启动 Flask 应用

在命令行中执行以下命令,使用 Gunicorn 启动应用:

bash 复制代码
gunicorn -w 4 -b 0.0.0.0:5000 run:app
  • -w 4: 指定启动 4 个工作进程。可以根据需要调整工作进程的数量。
  • -b 0.0.0.0:5000: 指定服务器监听的地址和端口。
  • run:app: 指定运行的模块和应用对象。

这个命令告诉 Gunicorn 启动应用,监听指定的地址和端口,并使用指定数量的工作进程来处理请求。

访问 http://127.0.0.1:5000/,确保应用在 Gunicorn 下正常运行。你将不再看到 Flask 的调试信息,而是 Gunicorn 提供的日志信息。

这样,你就成功地用 Gunicorn 作为 WSGI 服务器来运行 Flask 应用。在生产环境中,可以使用类似 Nginx 或 Apache 作为反向代理,将请求转发给 Gunicorn 处理,以提供更好的性能和可扩展性。

2. Flask与APScheduler集成方案

APScheduler提供了BackgroundScheduler和BlockingScheduler两种类型的调度器,用于创建定时任务。

  • BackgroundScheduler在后台运行,不会阻塞主线程;
  • BlockingScheduler会阻塞主线程直到所有任务完成。

这里使用非阻塞BackgroundScheduler,如上文代码。

python 复制代码
scheduler = BackgroundScheduler(timezone=pytz.timezone("Asia/Shanghai") )

并且定义为全局变量。

3. 其他参考

Flask常用扩展包:

  • Flask-SQLalchemy:操作数据库;
  • Flask-migrate:管理迁移数据库;
  • Flask-Mail:邮件;
  • Flask-WTF:表单;
  • Flask-Bable:提供国际化和本地化支持,翻译;
  • Flask-script:插入脚本;
  • Flask-Login:认证用户状态;
  • Flask-OpenID:认证;
  • Flask-RESTful:开发REST API的工具;
  • Flask-Bootstrap:集成前端Twitter Bootstrap框架;
  • Flask-Moment:本地化日期和时间;
  • Flask-Admin:简单而可扩展的管理接口的框架

参考:

一抹浅笑. Python之flask框架. 博客园. 2019.01

我还可以熬_. Flask之jinja2模板(一). CSDN博客. 2022.10

黑马程序员Python. 如何最简单、通俗地理解Flask?. 知乎. 2022.09

范高伦. Flask框架. CSDN博客. 2019.10

相关推荐
Open-AI4 分钟前
Python如何判断一个数是几位数
python
极客代码7 分钟前
【Python TensorFlow】入门到精通
开发语言·人工智能·python·深度学习·tensorflow
义小深10 分钟前
TensorFlow|咖啡豆识别
人工智能·python·tensorflow
疯一样的码农14 分钟前
Python 正则表达式(RegEx)
开发语言·python·正则表达式
进击的六角龙1 小时前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
一只爱好编程的程序猿2 小时前
Java后台生成指定路径下创建指定名称的文件
java·python·数据下载
Aniay_ivy2 小时前
深入探索 Java 8 Stream 流:高效操作与应用场景
java·开发语言·python
gonghw4032 小时前
DearPyGui学习
python·gui
向阳12182 小时前
Bert快速入门
人工智能·python·自然语言处理·bert
engchina2 小时前
Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询
数据库·python·neo4j