`

(转载)Flask 出坑记

阅读更多

Flask 是个 Python Web 框架. 网站上文档例子都很详尽, 这里就不废话了, 只是来扯两个使用中需要注意的地方.
装饰器对被装饰函数的名字是敏感的

    首先是应用程序装饰器, 如官网上的例子

1
2
3
4
5
6
7
8
import flask
app = flask.Flask(__name__)
 
@app.route('/')
def hello():
    return 'Hello World'
 
if __name__ == '__main__': app.run(port=7777)


    这个装饰器挂在哪个函数上, 哪个函数就成为一个处理函数. 这个特性让那些看多了 django 或者 tornado 起手先一大堆类定义的人一下子全高潮了, 大呼简单函数拯救世界. 不过这东西有时候相当坑. 先来看一个熊孩子特性, 把上面代码改成这样

1
2
3
4
5
6
import flask
app = flask.Flask(__name__)
 
app.route('/')(lambda: 'Hello World')
 
if __name__ == '__main__': app.run(port=7777)


    然后试着 curl 一下 http://localhost:7777, 没问题, 还是返回 'Hello World'. 好, 加一句

1
2
3
4
5
6
7
import flask
app = flask.Flask(__name__)
 
app.route('/')(lambda: 'Hello World')
app.route('/wtf')(lambda: 'I bought a watch last year')
 
if __name__ == '__main__': app.run(port=7777)


    再来一发

1
2
3
4
$ curl http://localhost:7777/
I bought a watch last year
$ curl http://localhost:7777/wtf
I bought a watch last year


    怎么都是「I bought a watch last year」?! 我去年买了个表!
    查了一通文档才发现 Flask 会索引被装饰函数的名字, 并根据这些名字来派发请求. 好了, 结论是不要在 Flask 里玩 lambda, 因为 Python 里面所有 lambda 名字都一个样

1
2
3
4
5
6
>>> x = lambda : None
>>> x.__name__
'<lambda>'
>>> y = lambda m, n: m + n
>>> y.__name__
'<lambda>'


    傲娇程序员的第一反应可能是「才不会到处用 lambda 只是偶尔写一个换换口味」. 且慢, 倒不是说 lambda 有问题, 而是下面这种用况会出事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import flask
 
app = flask.Flask(__name__)
 
def handler_logger(f):
    def g(*args, **kwargs):
        print 'before request'
        r = f(*args, **kwargs)
        print 'after request'
        return r
    return g
 
@app.route('/')
@handler_logger
def root():
    return 'Hello World'
 
@app.route('/wtf')
@handler_logger
def wtf():
    return 'I bought a watch last year'
 
if __name__ == '__main__': app.run(port=7777)


    同样的结果, 访问两个 URL 看到的都是后一个函数的结果.
    刚才已经说了 Flask 对被包装函数的名字是敏感的, 所以解决上述问题的方法便是

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
import flask
import functools
 
app = flask.Flask(__name__)
 
def handler_logger(f):
    @functools.wraps(f)
    def g(*args, **kwargs):
        print 'before request'
        r = f(*args, **kwargs)
        print 'after request'
        return r
    return g
 
@app.route('/')
@handler_logger
def root():
    return 'Hello World'
 
@app.route('/wtf')
@handler_logger
def wtf():
    return 'I bought a watch last year'
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()


获取 POST 请求体

    21 世纪的 Web 交互中服务器跟浏览器互相丢 JSON 已经成了司空见惯的事情. 服务器上要搞到 JSON 数据当然是直接访问 POST 请求体了, 如

1
2
3
4
5
6
7
8
9
10
11
12
13
import flask
import functools
 
app = flask.Flask(__name__)
 
@app.route('/wtf', methods=['POST'])
def wtf():
    return 'Received: ' + flask.request.data
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()


    按文档的说法, flask.request.data 包含请求数据字符串. 但其实这也是个坑, 默认情况下根本取不到请求数据

1
$ curl -d "[1,1,2,3,5,8]" http://localhost:7777/wtf


Received:
    熊孩子你把拿到的字符串给吃了吧? 实际上如果去看看那文档会看到并不如上面所说的那样, 而是
Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
    后面这个状语从句真是着急, 那到底什么 mimetype 会使得 Flask does not handle 呢? 根本没说清楚啊. 扫一眼文档后面, 还有个东西可以用: flask.request.json, 但这货一般是 None, 只有当请求 mimetype 被设置为 application/json 的时候才有用, Flask 你真心是跟 mimetype 过不去啊. 也就是说得这样发请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import json
import flask
import functools
 
app = flask.Flask(__name__)
 
@app.route('/wtf', methods=['POST'])
def wtf():
    return 'Received: ' + json.dumps(flask.request.json)
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()

 

1
2
3
4
$ curl -d "[1,1,2,3,5,8]" localhost:7777/wtf
Received: null
$ curl -d "[1,1,2,3,5,8]" -H "Content-Type:application/json" localhost:7777/wtf
Received: [1, 1, 2, 3, 5, 8]


    问题是现在前端攻城狮都被浏览器兼容性折腾得满世界买表, 哪还有心情检查每个请求的 content-type 对不对. 况且这还只对 JSON 有效, 如果是山寨协议又怂了.
    好吧, 如果实在不行, 就挖到 WSGI 里面去好了, 比如这样

1
2
3
4
5
def request_data():
    d = flask.request.data
    if not d:
        return ''.join(flask.request.environ['wsgi.input'].readlines())
    return d


    这样 (在特定的 WSGI 环境中, 比如配合 gevent 使用时) 能获取请求数据 (这不还是坑么). 或者看看这个万能的方法. 好了, 请求字符串快到碗里来!

分享到:
评论

相关推荐

    基于flask的数据库管理系统

    **基于Flask的数据库管理系统** 是一个使用Python编程语言构建的应用程序,主要依赖于三个关键库:`Faker`、`Flask` 和 `Flask-SQLAlchemy`。这个系统设计用于教学目的,如毕业设计、课后大作业,同时也适合进行二次...

    Flask v2.0 中文文档

    **Flask v2.0 中文文档概述** Flask 是一个轻量级的 Python Web 开发框架,基于 WSGI 协议。它以其简洁、灵活的架构深受开发者喜爱,适合构建小型到中等规模的 Web 应用。Flask v2.0 是该框架的一个重要版本,引入...

    Flask_Web全栈开发阶段-flask框架.zip

    在本压缩包“Flask_Web全栈开发阶段-flask框架.zip”中,核心主题是关于使用Flask框架进行Web全栈开发的知识。Flask是一个轻量级的Python Web服务器网关接口(WSGI)应用框架,由Armin Ronacher开发。它提供了基础的...

    python-flask-microservice_Flask框架_flask_phyton_

    EasyUI提供了一系列的JavaScript和CSS组件,可以快速构建出具有响应式布局的现代网页。在Flask应用中,可以通过引入EasyUI的静态资源,并在模板中使用其组件,实现交互式的用户界面。例如,可以创建一个表格展示数据...

    Python离线安装Flask

    在Python的开发环境中,有时我们可能需要在没有网络的情况下安装Flask框架,这通常发生在内网环境或者设备连接限制的场景。"Python离线安装Flask"的主题就是要解决这种问题。Flask是一款轻量级的Web服务程序,适用于...

    基于Flask的课堂扫脸考勤签到系统

    基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的...

    Flask+Web开发实战,flaskweb开发实战pdf,Python

    **Flask Web开发实战——Python Web开发的轻量级选择** Flask,作为一个轻量级的Python Web框架,自2010年开源以来,已经在开发者社区中积累了极高的声誉。与Django这样的全功能框架相比,Flask以其灵活性、简单性...

    flask及依赖项安装文件

    flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖...

    flask开发项目源码参考

    Flask是一种轻量级的Python Web框架,非常适合用于开发小型到中型的Web应用程序。在“flask开发项目源码参考”中,我们可以看到一个完整的Flask应用实例,包括其目录结构和各种接口案例。这个资源是个人测试开发版本...

    flask

    Flask 是一个轻量级的Web服务程序框架,基于Python编写,被广泛应用于构建小型到中型的Web应用。它的核心设计理念是“微”,强调模块化和可扩展性,允许开发者根据需求选择合适的扩展来增强功能,而不会带来不必要的...

    Flask-YOLOv8-Pytorch代码

    Flask与PyTorch结合使用YOLOv8的一般步骤: 环境准备: 确保安装了Python环境。 安装Flask:pip install Flask。 安装PyTorch:根据你的系统配置安装PyTorch,pip install torch torchvision。 获取YOLOv8模型: ...

    flask_pythonflask_flask书籍_图书管理系统_

    《Flask Python Flask:构建图书管理系统》 在Python Web开发领域,Flask框架因其轻量级、灵活性和易于上手的特性,深受开发者喜爱。本系统以“图书管理系统”为应用背景,旨在帮助读者理解如何利用Flask构建一个...

    python基于flask的管理系统源码.zip

    Python基于Flask的管理系统源码是一个实用的后端开发示例,它展示了如何利用Flask这一轻量级的Web框架构建一个完整的管理平台。Flask是Python中的一个微型Web服务框架,以其简洁、灵活的特点受到开发者们的欢迎。...

    Flask官方文档中文版

    此外,汇智网还提供了《深入浅出Flask》在线教程,其中包括预置的开发环境和互动式的实践环节,旨在帮助初学者更快速地理解和掌握Flask开发。在线课程内容广泛,覆盖了大量编程技术和工具,有助于开发者构建全面的...

    Flask文档.pdf

    Flask是一个轻量级的Web框架,最初由Armin Ronacher领导的Pocoo团队开发,它遵循 BSD 协议,因此它是完全开源的。Flask的设计目标是保持核心简单但可扩展,这允许开发者自由选择合适的工具和库来完成工作,而不是...

    Flask+Vue 仓储物资管理系统

    Flask可以通过接收前端的出入库请求,处理库存变化,同时记录详细的交易日志。Vue可以提供直观的出入库界面,简化操作流程,降低出错概率。 数据统计与分析是提升管理决策质量的关键。Flask可以连接到数据可视化库...

    Flask Web电子教程

    **Flask Web开发详解** Flask是一个轻量级的Python Web框架,因其简洁、灵活的特性,被广大开发者所喜爱。本教程将深入探讨Flask的核心概念和实用技巧,帮助你快速掌握使用Flask构建Web应用的方法。 1. **Flask...

    Pear Admin Flask 基于 Flask 的后台管理系统,拥抱应用广泛的python语言,通过使用本系统,即可快速构建

    Pear Admin Flask 基于 Flask 的后台管理系统,拥抱应用广泛的python语言,通过使用本系统,即可快速构建你的功能业务 项目旨在为 python 开发者提供一个后台管理系统的模板,可以快速构建信息管理系统。 项目使用...

    flask课件资料.rar

    ** Flask 框架基础知识概览 ** Flask 是一个轻量级的 Python Web 开发框架,由 Armin Ronacher 创建。它以其简洁、灵活的架构而受到开发者的喜爱,适用于构建小型到中型的 Web 应用。本课件资料主要针对 Flask 的...

    Flask PDF中文文档

    "Flask中文文档" 本文档是对Flask框架的详细介绍,涵盖了安装、快速上手、项目布局、应用设置、数据库、蓝图和视图、模板、静态文件、博客蓝图、项目可安装化、测试、部署、产品继续开发等方面的知识点。 一、安装...

Global site tag (gtag.js) - Google Analytics