Python Web Flask源码解读!启动流程!

Python项目源码7_简单的Web服务器.rar 立即下载

0x00 什么是WSGI

Web Server Gateway Interface 

它由 Python 标准定义的一套 Web Server 与 Web Application 的 接口交互规范 。

WSGI 不是一个应用、框架、模块或者库,而是规范。、

Python资源共享群:626017123

那什么是 Web Server ( Web 服务器)和什么是 Web Application ( Web 应用)呢?

举例子来说明容易理解,例如常见的 Web 应用框架有 Django 、 Flask 等,而 Web 服务器有 uWSGI 、 Gunicorn 等。 WSGI 就是定义了这两端接口交互的规范。

0x01 什么是Werkzeug

Werkzeug is a comprehensive WSGI web application library.

Werkzeug 是一套实现 WSGI 规范的函数库。我们可以使用它来创建一个 Web Application ( Web 应用)。例如本文介绍的 Flask 应用框架就是基于 Werkzeug 来开发的。

这里我们使用 Werkzeug 启动一个简单的服务器应用

from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
    return Response('Hello, World!')
if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, application)

运行之后可以在控制台上将看到如下信息

* Running on http://localhost:4000/ (Press CTRL+C to quit)

使用浏览器打开 http://localhost:4000/ 看到以下信息,说明

Hello, World!

0x02 什么是Flask

Flask is a lightweight WSGI web application framework.

Flask 是一个轻量级的 web 应用框架,它是跑在 web 服务器中的一个应用。 Flask 底层就是封装的 Werkzeug 。

使用 Flask 开发一个 web 应用非常简单

from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return f'Hello, World!'
if __name__ == '__main__':
    app.run()

很简单吧。

接下来我们看看 Flask 应用的启动流程。

0x03 启动流程

从项目地址 https://github.com/pallets/flask 中把源码 clone 下来,然后切换到0.1版本的 tag。为何要使用0.1版本呢?因为这个是作者最开始写的版本,代码量应该是最少的,而且可以很容易看到作者整体编码思路。

下面就从最简单的 Demo 开始看看 Flask 是如何启动的。我们知道程序启动是执行了以下方法

if __name__ == '__main__':
    app.run()

而

app = Flask(__name__)

打开 Flask 源码中的 __init__ 方法

Flask.__init__()

def __init__(self, package_name):
        #: 是否打开debug模式
        self.debug = False
        #: 包名或模块名
        self.package_name = package_name
        #: 获取app所在目录
        self.root_path = _get_package_path(self.package_name)
        #: 存储视图函数的字典,键为函数名称,值为函数对象,使用@route装饰器进行注册
        self.view_functions = {}
        #: 存储错误处理的字典.  键为error code, 值为处理错误的函数,使用errorhandler装饰器进行注册
        self.error_handlers = {}
        #: 处理请求前执行的函数列表,使用before_request装饰器进行注册
        self.before_request_funcs = []
        #: 处理请求前执行的函数列表,使用after_request装饰器进行注册
        self.after_request_funcs = []
        #: 模版上下文
        self.template_context_processors = [_default_template_ctx_processor]
        #: url 映射
        self.url_map = Map()
        
        #: 静态文件
        if self.static_path is not None:
            self.url_map.add(Rule(self.static_path + '/<filename>',
                                  build_only=True, endpoint='static'))
            if pkg_resources is not None:
                target = (self.package_name, 'static')
            else:
                target = os.path.join(self.root_path, 'static')
            self.wsgi_app = SharedDataMiddleware(self.wsgi_app, {
                self.static_path: target
            })
        #: 初始化 Jinja2 模版环境. 
        self.jinja_env = Environment(loader=self.create_jinja_loader(),
                                     **self.jinja_options)
        self.jinja_env.globals.update(
            url_for=url_for,
            get_flashed_messages=get_flashed_messages
        )

在 Flask 的构造函数中进行了各种初始化操作。

然后就是执行app.run()方法

app.run()

def run(self, host='localhost', port=5000, **options):
    """启动本地开发服务器.  如果debug设置为True,那么会自动检查代码是否改动,有改动则会自动执行部署
    :param host: 监听的IP地址. 如果设置为 ``'0.0.0.0'``就可以进行外部访问
    :param port: 端口,默认5000
    :param options: 这个参数主要是对应run_simple中需要的参数
    """
    from werkzeug.serving import run_simple
    if 'debug' in options:
        self.debug = options.pop('debug')
    options.setdefault('use_reloader', self.debug)
    options.setdefault('use_debugger', self.debug)
    return run_simple(host, port, self, **options)

run 很简洁,主要是调用了 werkzeug.serving 中的 run_simple 方法。

再打开 run_simple 的源码

rum_simple()

def run_simple(hostname, port, application, use_reloader=False,
               use_debugger=False, use_evalex=True,
               extra_files=None, reloader_interval=1, threaded=False,
               processes=1, request_handler=None, static_files=None,
               passthrough_errors=False, ssl_context=None):
    # 这方法还是比较短的,但是注释写得很详细,由于篇幅问题,就把源码中的注释省略了
    if use_debugger:
        from werkzeug.debug import DebuggedApplication
        application = DebuggedApplication(application, use_evalex)
    if static_files:
        from werkzeug.wsgi import SharedDataMiddleware
        application = SharedDataMiddleware(application, static_files)
    def inner():
        make_server(hostname, port, application, threaded,
                    processes, request_handler,
                    passthrough_errors, ssl_context).serve_forever()
    if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
        display_hostname = hostname != '*' and hostname or 'localhost'
        if ':' in display_hostname:
            display_hostname = '[%s]' % display_hostname
        _log('info', ' * Running on %s://%s:%d/', ssl_context is None
             and 'http' or 'https', display_hostname, port)
    if use_reloader:
        # Create and destroy a socket so that any exceptions are raised before
        # we spawn a separate Python interpreter and lose this ability.
        test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        test_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        test_socket.bind((hostname, port))
        test_socket.close()
        run_with_reloader(inner, extra_files, reloader_interval)
    else:
        inner()

在 rum_simple 方法中还定义一个嵌套方法 inner() ,这个是方法的核心部分。

inner()

def inner():
    make_server(hostname, port, application, threaded, processes, request_handler, passthrough_errors, ssl_context).serve_forever()

在 inner() 方法里面,调用 make_server(...).serve_forever() 启动了服务。

make_server()

def make_server(host, port, app=None, threaded=False, processes=1,
                request_handler=None, passthrough_errors=False,
                ssl_context=None):
    """Create a new server instance that is either threaded, or forks
    or just processes one request after another.
    """
    if threaded and processes > 1:
        raise ValueError("cannot have a multithreaded and "
                         "multi process server.")
    elif threaded:
        return ThreadedWSGIServer(host, port, app, request_handler,
                                  passthrough_errors, ssl_context)
    elif processes > 1:
        return ForkingWSGIServer(host, port, app, processes, request_handler,
                                 passthrough_errors, ssl_context)
    else:
        return BaseWSGIServer(host, port, app, request_handler,
                              passthrough_errors, ssl_context)

在 make_server() 中会根据线程或者进程的数量创建对应的 WSGI 服务器。 Flask 在默认情况下是创建 BaseWSGIServer 服务器。

BaseWSGIServer、ThreadedWSGIServer、ForkingWSGIServer

class BaseWSGIServer(HTTPServer, object):
    ...
class ThreadedWSGIServer(ThreadingMixIn, BaseWSGIServer):
    """A WSGI server that does threading."""
    ...
class ForkingWSGIServer(ForkingMixIn, BaseWSGIServer):
    """A WSGI server that does forking."""
    ...

可以看出他们之前的继承关系如下

 

 

 

 

 

 

打开 BaseWSGIServer 的 start_server() 方法

start_server()

def serve_forever(self):
    try:
        HTTPServer.serve_forever(self)
    except KeyboardInterrupt:
        pass

可以看到最终是使用 HTTPServer 中的启动服务的方法。而 HTTPServer 是 Python 标准类库中的接口。

HTTPServer 是 socketserver.TCPServer 的子类

socketserver.TCPServer

如果要使用 Python 中类库启动一个 http server ,则类似代码应该是这样的

import http.server
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

至此,整个服务的启动就到这里就启动起来了。

这个过程的调用流程为

graph TD
A[Flask]-->B[app.run]
B[app.run]-->C[werkzeug.run_simple]
C[werkzeug.run_simple]-->D[BaseWSGIServer]
D[BaseWSGIServer]-->E[HTTPServer.serve_forever]
E[HTTPServer.serve_forever]-->F[TCPServer.serve_forever]

0x04 总结一下

WSGI 是 WEB 服务器与 WEB 应用之间交互的接口规范。 werkzeug 是实现了这一个规范的函数库,而 Flask 框架是基于 werkzeug 来实现的。

我们从 Flask.run() 方法启动服务开始,追踪了整个服务启动的流程。

56个PythonWeb源码分享[可运行源码] 本文分享了56个PythonWeb系统源码,涵盖了多种应用场景,包括博客系统、投票系统、药品管理系统、人脸识别考勤系统等。这些源码基于不同的Python框架如Flask、Django开发,适合不同需求的开发者使用。文章还提供了源码的下载链接,方便读者获取和使用。这些项目不仅有助于学习PythonWeb开发,还能为实际项目提供参考和灵感。 立即下载

相关推荐

RYU+mininet——RYU

1. 使用RYU做mininet的控制器 1.1 RYU介绍与安装 RYU是一款基于python的控制器,你可用Ryu实现各种想要实现的网络功能,它可以下发或接收流表进行各种路由运算。 建议使用高版本的Ubuntu系统安装ryu,否则会有各种错误,安装过程比较简单,如下: apt install gcc libffi-dev libssl-dev libxml2-dev libxslt1-...

qq_34415266的博客 1万+

python配什么电脑好_自学python用什么配置电脑?

Python开发web服务的优势是开发效率高,可能只需要java五分之一的代码量。Python搭建web服务有许多框架,本文介绍Django和bottle两个框架。Django安装首先,安装该框架安装成功,版本是1.11.28. 框架的文件安装在\python27\Scripts目录下(搜索电脑中Python安装目录下的Scripts就对了)。建立项目先进入\python27\Scripts目录,...

weixin_39885067的博客 406

遥感数据下载——FIRM:VIIRS火点数据、MODIS火点数据简介及下载

一、FIRMS(Fire Information for Resoutce Management System) 网站链接:https://firms.modaps.eosdis.nasa.gov/map/ 这个网站上对VIIRS及MODIS的火灾数据进行了显示,可以进行按日期、产品类别等动态的展示火点数据或火烧迹地,同时也提供了数据下载控件。高级选择中还可以进行数据统计结果展示。 二、VIIR...

knkn123的博客 3万+

Python Web Flask源码解读(一)

关于我 编程界的一名小小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 联系:hylinux1024@gmail.com 0x00 什么是WSGI Web Server Gateway Interface 它由Python标准定义的一套Web Server与Web Application的接口交互规范。 W...

weixin_30337157的博客 464

PMOS缓启动电路设计实战:用LTspice优化上电时序,把60A冲击降到15A

本文通过一个实战案例,深入解析了PMOS缓启动电路如何有效抑制上电冲击电流。文章指出,低ESR电容是导致冲击电流飙升的元凶,并详细阐述了利用LTspice仿真工具,通过优化栅极电阻和栅源电容等参数,将高达60A的冲击电流成功降至15A的设计与优化过程,为电源开关电路设计提供了可复用的方法论。

onion的博客 899

华为模拟器eNSP练习题 - HCIA综合实验

华为模拟器eNSP练习题 - HCIA综合实验 题目要求 ISP路由器只能配置IP地址,之后不得进行其他任何配置; 整个内部网络基于192.168.1.0/24进行地址规划; R1/R2之间启动OSPF协议,单区域; PC1-PC4自动获取IP地址; PC1不能telnet R1,PC1外的其他内网pc可以; PC1-PC4可以访问PC5,R2的公网接口只拥有一个公有IP12.0.0.1; 外部的client可以通过域名www.ensp.com访问http server; ISP路由telnet 12.0

炸鸡店老板z的博客 9870

[Python+Django]Web学生信息管理系统毕业设计之源码+论文篇

本文参考之前Python+Django Web学生信息管理系统的博文,协助某同学完成的毕业设计论文。某同学已经答辩顺利通过, 现将一起完成论文的过程文件全部分享出来供大家参考。Python+Django学生信息管理系统源码Django学生信息管理系统运行说明手册(PDF)基于Python的Web学生信息管理系统的论文(总字数超1万字)学生信息管理系统E-R实体图(Visio可编辑文件)学生信息管理系统架构图(mindmaster思维导图可编辑文件)

李威威wiwi的博客 6461

MTK6769平台Type-C充电全解析:从硬件管脚到PD协议实战(Android15环境)

本文深入解析了MTK6769平台在Android 15环境下Type-C充电的完整链路。从硬件管脚(特别是核心的CC引脚)功能与连接,到USB-PD协议报文抓取与实战分析,并结合MTK平台PD芯片驱动与充电IC驱动的软件框架,提供了从硬件设计到软件调试的系统性解决方案和常见问题排查案例。

ol78901234的博客 311

flask项目源码_Python Web Flask源码解读(一)——启动流程

关于我一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。Github:https://github.com/hylinux1024微信公众号:终身开发者(angrycode)0x00 什么是WSGIWeb Server Gateway Interface它由Python标准定义的一套We...

weixin_29466045的博客 320

【异常】XXL-JOB提示异常ERROR com.xxl.job.core.util.XxlJobRemotingUtil - connect timed out

打开XXL-JOB的ELK,发现一堆报错。

奶爸的编程之路,也就一周冷个三天 2048

MFC实现简单UDP通信(附完整源码)

MFC实现简单UDP通信(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1109

python flask源码_Python Web Flask源码解读(一)——启动流程

关于我一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。Github:https://github.com/hylinux1024微信公众号:终身开发者(angrycode)0x00 什么是WSGIWeb Server Gateway Interface它由Python标准定义的一套We...

weixin_39553705的博客 313

道路施工检测 (construction) - 基于Mapillary Vistas数据集的YOLOv11目标检测及UI界面实现

目标检测是计算机视觉的重要任务,目标是识别图像中的目标物体类别及其位置(用边界框表示)。两阶段检测器:如Faster R-CNN,准确度高但速度较慢单阶段检测器:如YOLO系列、SSD,速度快且精度相对较好,适合实时场景数据量:约25,000张高分辨率街景图标注类型:语义分割、实例分割、多类别检测类别示例:construction, road, car, person, traffic sign等格式:COCO风格JSON标注。

YOLO 496

Python Web Flask源码解读(一)——启动流程

开始学习Flask源码

终身开发者 299

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

python flask源码_Python Web Flask源码解读(一)

关于我编程界的一名小小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。联系:hylinux1024@gmail.com0x00 什么是WSGIWeb Server Gateway Interface它由Python标准定义的一套Web Server与Web Application的接口交互规范。WSGI不是一个应...

weixin_39827506的博客 312

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Flask初版架构源码解读 | Python基础

WSGI是什么? WSGI即Web Server Gateway Interface 是基于现存的CGI标准而设计的,是Python对CGI进行的一种包装 也是一个规范,定义了Web服务器如何与Python应用程序进行交互,使得使用Python写的Web应用程序可以和Web服务器对接起来 目前Django、Flask等主流Python Web框架都实现了WSGI WSGI Web架构 对于一个遵守WSGI协议的服务器和Web应用来说, 它并不在意到底是谁传过来的数据, 只需要知道传过来

731

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

flask_python_web框架源码阅读(1)

引言 还是老样子,想研究源码,从最新版看没有太大的意义,最好是从第一个版本v0.1开始看起,因为东西最少,但是涉及到的整个框架的设计思路是基本上不会变的··· 文章目录一些概念flaskwerkzeugwsgiweb server /web application简单了解werkzeug开始了解flask快速开发一个hello,world应用源码分析实例化过程run源码阅读run_simple源码阅读serve_forever阅读源码本回合总结 一些概念 flask 这是对flask的最初始的描述 A mi

技顽Mark的博客 574

Python Web Flask源码解读!模板渲染过程!

关于我 编程界的一名小小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 Github: github.com/hylinux1024 微信公众号:angrycode Python资源共享群:484031800 前面对 Flask 启动流程 和路由原理都进行了源码走读。今天我们看看 模板渲染 的过程。 ...

Pythoncxy的博客 375

python web 模版_Python Web Flask源码解读!模板渲染过程!

关于我编程界的一名小小程序猿,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。微信公众号:angrycodePython资源共享群:484031800前面对 Flask 启动流程 和路由原理都进行了源码走读。今天我们看看 模板渲染 的过程。0x00 使用模板首先看一个来自官方文档使用模板渲染的例子from flask...

weixin_39637589的博客 245

Python Web Flask源码解读(三)——模板渲染过程

关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。 Github:https://github.com/hylinux1024 微信公众号:终身开发者(angrycode) 前面对Flask启动流程和路由原理都进行了源码走读。今天我们看看模板渲染的过程。 0x00 ...

weixin_30364147的博客 274

python flask源码解析_Flask源码解读(一)

Flask是一个使用 Python 编写的轻量级 Web 应用框架。Flask 本身只是 Werkezug 和 Jinja2 的之间的桥梁,前者实现一个合适的 WSGI 应用,后者处理模板。 当然, Flask 也绑定了一些通用的标准库包,比如 logging 。 除此之外其它所有一切都交给扩展来实现。我将追踪一个简单FlaskApp的运行,看看request和response是怎么实现,以下是一...

weixin_39583623的博客 496

python flask快速入门与进阶下载_Python Flask快速入门与进阶

Python Flask快速入门与进阶掌握了Python基础语法的同学,都知道下一步要学习Python框架了,但选什么框架,如何快速的渡过这个“卡顿”期,一直是个“老大难”问题。我们建议小白可以通过Flask来过渡与入门,FLask 本身“轻”的特点,让你的学习不会那么“重”,掌握核心知识就能进行开发 ,更容易获得成就感,学习也就会更有动力,另外,FLask虽轻,但Flask 很强,内核+扩展的特...

weixin_39524984的博客 182

python模板过程_Python Web Flask源码解读(三)——模板渲染过程

关于我一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android、Python、Java和Go,这个也是我们团队的主要技术栈。Github:https://github.com/hylinux1024微信公众号:终身开发者(angrycode)前面对Flask启动流程和路由原理都进行了源码走读。今天我们看看模板渲染的过程。0x00 使用模板首先看一个来自官...

weixin_39674028的博客 258
上一篇: Python数据分析之pandas基本数据结构:Series、DataFrame!
下一篇: Python 神工具包!翻译、文字识别、语音转文字统统搞定!
普通网友
博客等级 码龄7年 438粉丝 263原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值