首页 > 编程语言 >Python——Flask相关原理

Python——Flask相关原理

时间:2023-04-04 18:09:40浏览次数:32  
标签:__ run name Python app Flask 原理 self


摘要

主要是介绍的Flask的原理和实现。主要是的在python的开发中常用Flask的框架。本博文对Flask的原理和应用进行详细的学习和介绍。

Flask

Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAIchemy),都需要用第三方的扩展来实现。比如可以用Flask扩展ORM体验证工具,文件上传、身份验证等。Flask没有默认使用的数据库,你可以选择MySQL,也可以用NoSQL。其WSGI工具箱采用Werkzeug (路由模块),模板引擎则使用Jinja2。这两个也是Flask框架的核心。

框架的对比

1)框架轻重

  • 重量级的框架:为方便业务程序的开发,提供了丰富的工具、组件,如Django
  • 轻量级的框架︰只提供Web框架的核心功能,自由、灵活、高度定制,如Flask、Tornado

2)与Django对比

  • 1django提供了︰django-admin快速创建项目工程目录
  • 2manage.py管理项目工程
  • 3orm模型(数据库抽象层)
  • 4admin后台管理站点缓存机制
  • 缓存机制
  • 文件存储系统
  • 用户认证系统

Flask的扩展

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

工程的搭建

1安装一个虚拟的python的环境(minconda):Conda——创建新的虚拟环境_庄小焱

from flask import Flask

#定义一个flask第一个参数__name__
app = Flask(__name__)# ->定义为字符串类型的模块名

@装饰器的作用是将映射到试图函数的index
@app.route('/')
def hello_world():
    return 'Hello World!'

# flask的应用程序的run方法启动web服务器
if __name__ == '__main__':
    app.run()

Flask对象的参数化

Flask对象的初始化参数

Flask 程序实例在创建的时候,需要默认传入当前Flask程序所指定的包(模块),接下来就来详细查看一下Flask应用程序在创建的时候一些需要我们关注的参数:

import_name:

  • Flask程序所在的包(模块),传__name__就可以。
  • 其可以决定Flask在访问静态文件时查找的路径.

static_url_path

  • 静态文件访问路径,可以不传,默认为︰/ + static_folder.
# app = Flask(__name_)#-> Flask(模块名字符串类型)
app = Flask(_name__, static_url_path='/s ')

static_folder

  • 静态文件存储的文件夹,可以不传,默认为static

template_folder

  • 模板文件存储的文件夹,可以不传,默认为templates

Python——Flask相关原理_静态文件

 Flask将配置信息保存到了app.config属性中,该属性可以按照字典类型进行操作。

读取:app.config.get(name)  app.config[name]

从配置对象中加载

app.config.from_object(配置对象)

from flask import Flask

# 配置对象的方式进行加载 继承复用 代码可以复用 但是敏感信息暴露
class DefaultConfig(object):
    """默认的配置"""
    SECRECT_KEY = "agfjagfjfaglfjkdfh;a"

app = Flask(__name__, static_url_path='/s', static_folder="/static")

# 从类中进行加载
app.config.from_object(DefaultConfig)

# 配置文件中加载   
# app.config.from_pyfile("./setting.py")

# 从环境变量加载变量  从环境变量指向的配置文件中读取的配置信息会覆盖揄从配置对象中加载的同名参数
app.config.from_envvar('PROJECT_SETTING')
app.config.from_envvar('PROJECT_SETTING', slice=True)

@app.route('/')
def hello_world():
    print(app.config['SECRECT_KEY'])
    return 'Hello World!'

if __name__ == '__main__':
    app.run()
export变量名=变量值#设置
echo $变量名#读取

#例如
export ITCAST=python
echo $ITCAST

app.run()运行参数

Python——Flask相关原理_静态文件_02

app.run(host="0.0.0.0", port=5000,debug = True)

Python——Flask相关原理_静态文件_03

环境变量FLASK_APP指明flask的启动实例
flask run -h 0.0.0.0 -p 8000绑定地址端口
flask run --help获取帮助

生产模式与开发模式的控制
通过FLASK_ENV环境变量指明
export FLASK_ENV=production运行在生产模式,未指明则默认为此方式
export FLASK_ENV=development运行在开发模式

Python——Flask相关原理_静态文件_04

Python——Flask相关原理_静态文件_05

Flask的请求原理

查询路由信息 命令行方式:flask routes(*)

# 获取的flask的所有的路由的路径信息
print(app.url_map)

Map([<Rule '/' (GET, HEAD, OPTIONS) -> hello_world>,
 <Rule '/s/<filename>' (GET, HEAD, OPTIONS) -> static>])

# 获取的flask的所有的路由的路径信息
for rule in app.url_map.iter_rules():
    print("name={},path={}".format(rule.endpoint, rule.rule))

请求方式

  • GET
  • OPTIONS:简化版的GET请求用于询问服务器接口信息的
  • CORS(跨域的访问):djanggo -cors ->中间都是拦截了options请求的。
比如接口允许的请求方式允许的请求源头域名

vwwvw.meiduo.site ->api.meiduo.site/users/1o 

options api.meiduo.site/uses/1

返回response -> allow-origin 

'www.meiduo.site'o GET api.meiduo.site/users/1
  • HEAD(自带)简化版GET请求 只返回GET请求处理时的响应头头,不返回响应体

Flask的蓝图原理

在Flask中,使用蓝图Blueprint来分模块组织管理。蓝图实际可以理解为是一个存储一组视图方法的容器对象,其具有如下特点:

  • 一个应用可以具有多个Bqeprint
  • 可以将一个Blueprint注册到任何一个未使用的URL下比如“/user”、“/goods”
  • Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
  • 在一个应用初始化时,就应该要注册需要使用的Blueprint

但是一个Blueprint并不是一个完整的应用,它不能独立于应用运行,必须要注册到某一个应用中。

使用蓝图可以分为三个步骤
1.创建一个蓝图对象
user_bp=$lueprint( 'user',__name__)

2.在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模版过滤器
@user_bp.route( ' / ')
def user_profile( ):
return 'user_profile'

3.在应用对象上注册这个蓝图对象
app.register_blueprint(user_bp)

Python——Flask相关原理_加载_06

Python——Flask相关原理_加载_07

 Flask 启动流程

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return "hello 懒编程"
if __name__ == '__main__': 
    app.run()

在代码中,通过 Flask(__name__)实例化了 Flask 类,对应的__init__() 方法如下

# flask/app.py
classs Flask(_PackageBoundObject):

def __init__(...):
# 对每次请求,创建一个处理通道。
self.config = self.make_config()
self.view_functions = {}
self.error_handler_spec = {}
self.before_request_funcs = {}
self.before_first_request_funcs = []
self.after_request_funcs = {}
self.teardown_request_funcs = {}
self.teardown_appcontext_funcs = []
self.url_value_preprocessors = {}
self.url_default_functions = {}
self.url_map = Map()
self.blueprints = {}
self._blueprint_order = []
self.extensions = {}

__init__() 方法中有大量的注释,注释中解释了这些变量的用途,但仅从变量名就知道,它们用于存储每次请求对应的信息,相当于一个处理通道。Flask 实例化后,接着利用 @app.route('/')装饰器的方式将 hello () 方法映射成了路由,相关代码如下:

Python——Flask相关原理_静态文件_08

 可以发现 route () 方法就是一个简单的装饰器,具体处理逻辑在 addurlrule () 方法中。

Python——Flask相关原理_flask_09

 从 addurlrule () 方法可以看出, @app.route('/')的主要作用就是将路由保存到 urlmap 中,将装饰的方法保存到 viewfunctions 中。需要注意的是,每个方法的 endpoint 必须不同,否则会抛出 AssertionError。最后调用了 app.run () 方法运行 Flask 应用,对应代码如下。

Python——Flask相关原理_加载_10

run () 方法进一步调用 werkzeug.serving 下的 run_simple () 方法启动 web 服务,其中 self 就是 Flask () 的 application。
逐层深入,runsimple() -> makeserver() -> BaseWSGIServer() -> WSGIRequestHandler
WSGIRequestHandler 类从名称就可以知,它主要用于处理满足 WSGI 协议的请求,该类中的 execute () 方法部分代码如下。

Python——Flask相关原理_flask_11

 简单而言,app.run () 会启动一个满足 WSGI 协议的 web 服务,它会监听指定的端口,将 HTTP 请求解析为 WSGI 格式的数据,然后将 environ, start_response 传递给 Flask () 实例对象。
类对象作为方法被调用,需要看到__call__() 方法,代码如需。

Python——Flask相关原理_flask_12

主要逻辑在 wsgiapp () 方法中,一开始进行了请求上下文的处理 (后面文章单独剖析 Flask 上下文相关源码),随后通过 fulldispatch_request () 方法找到当前请求路由对应的方法,调用该方法,获得返回,如果请求路由不存在,则进行错误处理,返回 500 错误。

 

Python——Flask相关原理_静态文件_13

fulldispatchrequest () 方法中最关键的逻辑在于 dispatch_request () 方法,该方法会将调用对应路由的处理函数并获得该函数的结果。此外还有 trytriggerbeforefirstrequestfunctions()、preprocessrequest()、finalizerequest () 方法,这些方法会执行我们自定义的各种钩子函数,这些钩子函数会存储在 beforerequestfuncs()、beforefirstrequestfuncs()、afterrequestfuncs () 方法中。最后,需要注意,app.run () 方法仅在开发环境中会被使用,通过上面的分析,已经知道 app.run () 背后就是使用 werkzeug 构建了一个简单的 web 服务,但这个 web 服务并不牢靠,生产环境通常利用 uWSGI,通过配置的形式,指定 WSGI app 所在文件来启动 Flask 应用。

标签:__,run,name,Python,app,Flask,原理,self
From: https://blog.51cto.com/u_13643065/6169202

相关文章

  • Python——异步编程案例
    摘要主要是讲解Python中的异步编程的下的实际的案例案例:异步操作redis案例:异步操作MySQL案例:FastAPl框架异步案例:异步爬虫课程总结......
  • python——异步编程代码实战
    摘要主要介绍python中相关的异步编程的原理和是代码的实战协程实现协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。协程不是计算机提供,程序员人为创造。协程的优点:在一个线程中如果遇到IO等待时间,线程不......
  • Python——单元测试的实现
    摘要单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。在软件开中的测试是很重要的一部分。python测试相关库unittest,内置库,模仿PyUnit写的,简洁易用,缺点是比较繁琐。nose,测试发现,发现并运行测试。pytest,笔者目前喜欢用这个,写起来很方便,并且很多知名开源项......
  • SpringCloud——SpringCloud Alibaba Sentinel原理与实战
    摘要在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖。由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟而这些问题会直接导致调用方的对外服务也出现延......
  • SpringCloud——SpringCloud Sleuth原理与实战
    摘要SpringCloudEureka是SpringCloudNetflix微服务套件中的一部分,它基于NetflixEureka做了二次封装,主要负责完成微服务架构中的服务治理功能。SpringCloud通过为Eureka增加了SpringBoot风格的自动化配置,我们只需通过简单引入依赖和注解配置就能让SpringBoot构建的微服务......
  • Dubbo——扩展(SPI)加载原理
    摘要Dubbo为了更好地达到OCP原则(即“对扩展开放,对修改封闭”的原则),采用了“微内核+插件”的架构。那什么是微内核架构呢?微内核架构也被称为插件化架构(Plug-inArchitecture),这是一种面向功能进行拆分的可扩展性架构。内核功能是比较稳定的,只负责管理插件的生命周期,不会因为系统功......
  • Spring——spring事务原理与实战
    摘要Spring为事务管理提供了丰富的功能支持。Spring事务管理分为编程式和声明式两种。编程式事务指的是通过编码方式实现事务;声明式事务基于AOP,将具体的逻辑与事务处理解耦。生命式事务管理使业务代码逻辑不受污染,因此实际使用中声明式事务用的比较多。声明式事务有两种方式,一种......
  • flask-day3——蓝图的使用、g对象、数据库连接池
    目录一、蓝图(blueprint)1、蓝图介绍2、蓝图的使用3、使用蓝图,划分小型项目目录4、使用蓝图,划分大型项目目录5、其他知识点二、g对象三、数据库连接池四、作业1、什么是gil锁,有什么作用2、python的垃圾回收机制是什么样的3、解释为什么计算密集型用多进程,io密集型用多线程一、蓝图......
  • python PIL个人使用记录
    pythonPIL个人使用记录1、gif转pngdefgif_to_png(filename:str):"""gif图片一帧一帧转换为很多png图片:paramfilename::return:"""filename=filename.strip()filename=os.path.abspath(filename)assertos.path.s......
  • Python系列005
    控制设备仪器————电源初识importpyvisa#ConnecttotheGPIBinstrumentrm=pyvisa.ResourceManager()classPiDevice:def__init__(self,addressId):self.addressId=addressIddefPiPower(self):whoPower=rm.open_resource(self.a......