python Flask使用教程

python Flask的安装使用教程

安装

python版本为python3,安装Flask库。

1
pip3 install flask

使用

Hello World

创建myapp.py,输入以下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 导入Flask类
from flask import Flask
# 实例化,可视为固定格式
app = Flask(__name__)

# route()方法用于设定路由
@app.route('/')
def hello_world():
return 'Hello, World!'

if __name__ == '__main__':
# app.run(host, port, debug, options)
# 默认值:host="127.0.0.1", port=5000, debug=False
app.run(host="0.0.0.0", port=5000)

直接运行该文件

1
python3 myapp.py

然后浏览器访问:http://127.0.0.1:5000 。 得到返回结果Hello, World!

get、post用法

模板文件

Flask默认到templates目录下查找模板文件,在上边myapp同级目录下创建templates文件夹。

在templates文件夹下创建get.html,写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>get请求示例</title>
</head>
<body>
<form action="/deal_request" method="get">
<input type="text" name="q" />
<input type="submit" value="搜索" />
</form>
</body>
</html>

再在templates文件夹下创建post.html,写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>post请求示例</title>
</head>
<body>
<form action="/deal_request" method="post">
<input type="text" name="q" />
<input type="submit" value="搜索" />
</form>
</body>
</html>

最后在templates文件夹下创建result.html,写入以下内容:

1
2
<!-- Flask 使用Jinja2模板引擎,Jinja2模板引擎源于Django板模所以很多语法和Django是类似的 -->
<h1>{{ result }}</h1>

处理方法

在app.py中添加get_html()、post_html()和deal_request()三个方法,更多说明见注释。当前myapp.py内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 导入Flask类
from flask import Flask
from flask import render_template
from flask import request
# 实例化,可视为固定格式
app = Flask(__name__)

# route()方法用于设定路由;类似spring路由配置
#等价于在方法后写:app.add_url_rule('/', 'helloworld', hello_world)
@app.route('/')
def hello_world():
return 'Hello, World!'

# 配置路由,当请求get.html时交由get_html()处理
@app.route('/get.html')
def get_html():
# 使用render_template()方法重定向到templates文件夹下查找get.html文件
return render_template('get.html')

# 配置路由,当请求post.html时交由post_html()处理
@app.route('/post.html')
def post_html():
# 使用render_template()方法重定向到templates文件夹下查找post.html文件
return render_template('post.html')

# 配置路由,当请求deal_request时交由deal_request()处理
# 默认处理get请求,我们通过methods参数指明也处理post请求
# 当然还可以直接指定methods = ['POST']只处理post请求, 这样下面就不需要if了
@app.route('/deal_request', methods = ['GET', 'POST'])
def deal_request():
if request.method == "GET":
# get通过request.args.get("param_name","")形式获取参数值
get_q = request.args.get("q","")
return render_template("result.html", result=get_q)
elif request.method == "POST":
# post通过request.form["param_name"]形式获取参数值
post_q = request.form["q"]
return render_template("result.html", result=post_q)

if __name__ == '__main__':
# app.run(host, port, debug, options)
# 默认值:host=127.0.0.1, port=5000, debug=false
app.run()

运行后访问http://127.0.0.1:5000/get.html http://127.0.0.1:5000/post.html查看运行效果。

返回json数据的用法

以json等格式(而非以前的表单格式)发起请求,并以json等格式(而非以前的html)进行响应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# 导入Flask类
from flask import Flask, jsonify
from flask import render_template
from flask import request

# 实例化,可视为固定格式
app = Flask(__name__)
# 调试模式,设置FLASK_DEBUG环境变量,并将值设置为1。或者设置app.debug=True,修改代码,会发现这次Flask会自动重启
# app.debug = True


# route()方法用于设定路由;类似spring路由配置
# 等价于在方法后写:app.add_url_rule('/', 'helloworld', hello_world)
@app.route('/')
def hello_world():
return 'Hello, World!'


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


# 配置路由,当请求get.html时交由get_html()处理
@app.route('/get.html')
def get_html():
# 使用render_template()方法重定向到templates文件夹下查找get.html文件
return render_template('get.html')


# 配置路由,当请求post.html时交由post_html()处理
@app.route('/post.html')
def post_html():
# 使用render_template()方法重定向到templates文件夹下查找post.html文件
return render_template('post.html')


# 配置路由,当请求deal_request时交由deal_request()处理
# 默认处理get请求,我们通过methods参数指明也处理post请求
# 当然还可以直接指定methods = ['POST']只处理post请求, 这样下面就不需要if了
@app.route('/deal_request', methods=['GET', 'POST'])
def deal_request():
if request.method == "GET":
# get通过request.args.get("param_name","")形式获取参数值
get_q = request.args.get("q", "")
return render_template("result.html", result=get_q)
elif request.method == "POST":
# post通过request.form["param_name"]形式获取参数值
post_q = request.form["q"]
return render_template("result.html", result=post_q)


@app.route('/rest_test', methods=['POST'])
def hello_world1():
"""
通过request.json以字典格式获取post的内容
通过jsonify实现返回json格式
"""
post_param = request.json
result_dict = {
"result_code": 2000,
"post_param": post_param
}
return jsonify(result_dict)


if __name__ == '__main__':
# app.run(host, port, debug, options)
# 默认值:host=127.0.0.1, port=5000, debug=false
app.run(host="127.0.0.1", port=5000, debug=True)

使用curl进行请求

1
curl -H "Content-Type:application/json" -X POST --data '{"username": "ls","password":"toor"}' http://127.0.0.1:5000/rest_test

得到返回结果

更多相关使用参考官方文档

服务端部署

使用uwsgi在服务端启动应用

uwsgi 若为安装,使用如下命令进行安装

1
pip3 install uwsgi

命令行启动

uwsgi 是基于 python 模块中的 WSGI 调用的。示例中 Flask 应用名称为 app.py , 使用如下命令在5000端口启动

1
uwsgi --http-socket 127.0.0.1:5000 --manage-script-name --mount /app=myapp:app

--manage-script-name 会把 SCRIPT_NAME 处理移向 uwsgi , 因为 uwsgi 会更智能一些。与 --mount 联用可以把向 /app 发送的请求 重定向到 myapp:app 。如果应用可以在根级别访问,那么可以使用单个 / 来代替 /appmyapp 指 flask 应用的文件名称(不含扩展 名)或者提供 app 的模块名称。 app 在应用内部可被调用 (通常是 app = Flask(__name__)

配置文件启动

命令行启动在控制台窗口关闭时应用也就停止运行了,配置文件启动可以使应用运行在后台,不随着控制台窗口的关闭而停止运行。

在项目目录下创建uwsgi.ini文件,内容如下

1
2
3
4
5
6
7
8
[uwsgi]
http-socket = 127.0.0.1:5000
module = myapp:app
daemonize = ./uwsgi.log
pidfile=uwsgi.pid
#以下根据需要配置
#manage-script-name
#mount = /app=app:app

使用如下命令启动

1
uwsgi --ini uwsgi.ini

启动后在项目目录下生成uwsgi.loguwsgi.pid,分别用于存储运行日志和运行的进程id

整体目录结构如下

停止命令

1
uwsgi --stop uwsgi.pid

使用gunicorn在服务端启动应用

Gunicorn 是一个 UNIX 下的 WSGI HTTP 服务器,它是一个 移植自 Ruby 的 Unicorn 项目的 pre-fork worker 模型。

安装gunicorn

1
pip install gunicorn

命令行启动

在 Gunicorn 上运行 Flask 应用非常简单:

1
gunicorn myapp:app

使用更多参数运行

1
gunicorn -w 4 -b 127.0.0.1:4000 myapp:app

使用 4 worker 进程( -w 4 )来运行 Flask 应用,绑定到 localhost 的 4000 端口( -b 127.0.0.1:4000

gunicorn 命令需要应用或者包的名称和应用实例。如果使用工厂模式,那么可以传递一个调用来实现:

1
gunicorn "myproject:create_app()"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-c CONFIG    : CONFIG,配置文件的路径,通过配置文件启动;生产环境使用;
-b ADDRESS : ADDRESS,ip加端口,绑定运行的主机;
-w INT, --workers INT:用于处理工作进程的数量,为正整数,默认为1;
-k STRTING, --worker-class STRTING:要使用的工作模式,默认为sync异步,可以下载eventlet和gevent并指定
--threads INT:处理请求的工作线程数,使用指定数量的线程运行每个worker。为正整数,默认为1。
--worker-connections INT:最大客户端并发数量,默认情况下这个值为1000。
--backlog int:未决连接的最大数量,即等待服务的客户的数量。默认2048个,一般不修改;
-p FILE, --pid FILE:设置pid文件的文件名,如果不设置将不会创建pid文件
--access-logfile FILE : 要写入的访问日志目录
--access-logformat STRING:要写入的访问日志格式
--error-logfile FILE, --log-file FILE : 要写入错误日志的文件目录。
--log-level LEVEL : 错误日志输出等级。
--limit-request-line INT : HTTP请求头的行数的最大大小,此参数用于限制HTTP请求行的允许大小,默认情况下,这个值为4094。值是0~8190的数字。
--limit-request-fields INT : 限制HTTP请求中请求头字段的数量。此字段用于限制请求头字段的数量以防止DDOS攻击,默认情况下,这个值为100,这个值不能超过32768
--limit-request-field-size INT : 限制HTTP请求中请求头的大小,默认情况下这个值为8190字节。值是一个整数或者0,当该值为0时,表示将对请求头大小不做限制
-t INT, --timeout INT:超过这么多秒后工作将被杀掉,并重新启动。一般设定为30秒;
--daemon: 是否以守护进程启动,默认false;
--chdir: 在加载应用程序之前切换目录;
--graceful-timeout INT:默认情况下,这个值为30,在超时(从接收到重启信号开始)之后仍然活着的工作将被强行杀死;一般使用默认;
--keep-alive INT:在keep-alive连接上等待请求的秒数,默认情况下值为2。一般设定在1~5秒之间。
--reload:默认为False。此设置用于开发,每当应用程序发生更改时,都会导致工作重新启动。
--spew:打印服务器执行过的每一条语句,默认False。此选择为原子性的,即要么全部打印,要么全部不打印;
--check-config :显示现在的配置,默认值为False,即显示。
-e ENV, --env ENV: 设置环境变量;

配置文件启动

gunicorn.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 并行工作进程数
workers = 4
# 指定每个工作者的线程数
threads = 2
# 监听内网端口5000
bind = '127.0.0.1:5000'
# 设置守护进程,后台运行
daemon = True
# 工作模式协程
worker_class = 'gevent'
# 设置最大并发量
worker_connections = 2000
# 设置进程文件目录
pidfile = '/var/run/gunicorn.pid'
# 设置访问日志和错误信息日志路径
accesslog = '/var/log/gunicorn_acess.log'
errorlog = '/var/log/gunicorn_error.log'
# 设置日志记录水平
loglevel = 'warning'

启动

1
gunicorn -c gunicorn.conf myapp:app

配置 nginx

官网给的nginx配置如下

一个 nginx 的基本 uWSGI 配置如下:

1
2
3
4
5
6
location = /yourapplication { rewrite ^ /yourapplication/; }
location /yourapplication { try_files $uri @yourapplication; }
location @yourapplication {
include uwsgi_params;
uwsgi_pass unix:/tmp/yourapplication.sock;
}

这个配置把应用绑定到 /yourapplication 。如果你想要在根 URL 下运行应用 非常简单:

1
2
3
4
5
location / { try_files $uri @yourapplication; }
location @yourapplication {
include uwsgi_params;
uwsgi_pass unix:/tmp/yourapplication.sock;
}

官网给的是使用sock文件进行访问,这里我们使用端口访问,简化配置如下

1
2
3
location /app {
proxy_pass http://127.0.0.1:5000/;
}

这里配置把应用绑定到 /app

修改nginx的配置文件后,使用如下命令重启nginx即可

1
nginx -s reload

Flask与Django比较

FLask和Django都是Python比较流行的web框架,进行一下比较

比较项 Django Flask 复杂度比较 说明
项目创建 Django需要用命令创建项目 Flask直接编写文件就可运行 Django复杂 Django需要用命令创建项目是因为要创建出整个项目框架
路由 Django使用专门的urls.py文件 Flask直接使用@app.route() Django笨重 Django类似Strut2的配置Flask类似Spring的配置,Flask感觉更好
get和post request.GET[‘name’]和request.POST[“name”] request.args.get(“name”,””)和request.form[“q”] 差不多 Flask格式上不统一
restful 使用django-resful框架 使用jsonify 差不多 Flask不需要单建一个app,更直观一些
数据库操作 django集成了对数据库的操作 Flask没集成对数据库的操作要另行直连或使用sqlalchemy 差不多 django复杂很大程度来源于对数据库的集成。

Django是Python最流行的Web框架但配置比较复杂,Flask是一个轻量级的框架配置比较简单如果项目比较小推荐使用Flask。

进一步来说,Flask的轻量来源其“暂时不用的功能都先不做处理”,Django复杂来源于其“可能用到的功能都先集成”

参考

Python3+Flask安装使用教程

Flask中文文档

Flask官网

在Centos7使用uWSGI部署Flask

打赏

请我喝杯咖啡吧~

支付宝
微信