• flask源码走读


    https://www.cnblogs.com/lgjbky/p/10669397.html

     

    Flask-Origin

    源码版本

    一直想好好理一下flask的实现,这个项目有Flask 0.1版本源码并加了注解,挺清晰明了的,我在其基础上完成了对Werkzeug的理解部分,大家如果想深入学习的话,可以参考werkzeug_flow.md.

    阅读前

    为了更容易理解Flask的实现原理,你需要对WSGI协议以及HTTP协议有一些了解,建议先简单浏览下面的基本知识:

    Flask内部实现大量依赖于Werkzeug,包括请求和响应对象,路由匹配,URL生成等等,你可以阅读Werkzeug的文档来深入了解这些内容的具体实现。另外,如果你对模板渲染部分的内容感兴趣,也可以考虑阅读Jinja2文档:

    werkzeug源码阅读,可以参考下面的函数打断点,再测试一个请求,理清过程。

    其实可以参考简化后web服务实现思路,socket建立后,监听recv到的请求信息(no_wsgi_dome.no_wsgi.Socket._handle)并解析,然后调用相应的app.route对应的view_func.整个过程可以大致分为两部分:
    1. app-> werkzeug-> http-> socket 启动端口监听,注册各种方法.
    2. socket recv到请求-> 初始化RequestHandlerClass-> 调用Flask.__call__, wsgi_app在请求上下文中执行预处理方法,视图方法,后响应方法等.
    

    flask启动流程,只追溯了app到http再到socket的启动,主流程就是BaseWSGIServer初始化调用了HTTPServer的初始化,进而初始化了BaseServer,在socketserver上启动了服务开始监听端口:

    flask.Flask.run -> werkzeug.serving.run_simple ->
    werkzeug.serving.run_simple.inner ->werkzeug.serving.make_server ->
    BaseWSGIServer->HTTPServer.__init__(self, get_sockaddr(host, int(port),self.address_family), handler) ->
    BaseServer.__init__(self, server_address, RequestHandlerClass) ->
    werkzeug.serving.run_simple.inner.srv.serve_forever() ->
    socketserver.BaseServer.serve_forever 建立socket服务开始监听,当ready也就是有recv到请求时开始 _handle_request_noblock
    

    flask处理请求流程,追溯了socket接受到请求后触发app处理请求的主流程:

    curl发出请求->socket接受到请求 ->
    SocketServer.BaseServer.serve_forever._handle_request_noblock ->
    SocketServer.BaseServer.process_request ->
    SocketServer.BaseServer.finish_request ->
    socketserver.BaseServer.__init__:self.RequestHandlerClass(request, client_address, self)  ->
    这里要找出RequestHandlerClass是如何初始化的,它的真身是什么 ->
    socketserver.TCPServer.__init__:BaseServer.__init__(self, server_address, RequestHandlerClass) ->
    http.server.HTTPServer(未重写__init__) ->
    werkzeug.serving.BaseWSGIServer:HTTPServer.__init__(self, get_sockaddr(host, int(port),self.address_family), handler) (此处handler就是WSGIRequestHandler) ->
    RequestHandlerClass的真身已经找到,就是WSGIRequestHandler 也就是说每次请求来了都初始化一个WSGIRequestHandler去处理 ->
    处理的入口应该是werkzeug.serving.WSGIRequestHandler.handle可是简单一看并没找到是如何开始处理请求的->
    往它的父类BaseHTTPRequestHandler中找也没有 ->
    再往上socketserver.StreamRequestHandler ->
    找到了SocketServer.BaseRequestHandler.__init__:try:self.handle() 关键点 ->
    开始调用子类WSGIRequestHandler中的handle方法 ->
    werkzeug.serving.WSGIRequestHandler (注意handler和handle_one_request,WSGIRequestHandler重载了BaseHTTPServer.BaseHTTPRequestHandler中的方法,BaseHTTPRequestHandler由重载了 SocketServer.BaseRequestHandler )->
    werkzeug.serving.WSGIRequestHandler.handle_one_request调用werkzeug.serving.WSGIRequestHandler.run_wsgi 开始处理请求 ->
    run_wsgi.execute(self.server.app)将请求交予app来处理 ->
    flask.Flask.__call__ -> 
    flask.Flask.wsgi_app 开始app内的流程,交由wsgi_app在请求上下文中执行预处理方法,视图方法,后响应方法等。
    

    可以看到实现过程中Server,Handler用到了继承并重载,层层包装了web服务

    BaseWSGIServer继承了HTTPServer重写了BaseServer.serve_forever(包了一层),
    HTTPServer继承了TCPServer重写了server_bind,
    TCPServer继承了BaseServer重写了server_bind,
    主要思路要理清socket接受接请求后如何用请求触发调用app,这里主要是SocketServer.BaseRequestHandler.__init__:try:self.handle() 这个__init__才是处理请求真正开始的地方.
    

    进一步

    1. web的最原始的实现见 no_wsgi_dome ,不使用werkzeug,不使用wsgi约束,只是用socket如何实现http服务.这个对理解wsgi对http以及socket的封装有很好的借鉴意义.
    2. 补充了本地上下文相关的本地线程、本地堆栈、本地代理,并写了个LocalProxy_dome.py 辅助理解flask中是如何使用LocalProxy的。
    3. 我通过打断点,理通了app的启动和接受请求到处理请求的过程,可以参考werkzeug_flow.md配合flask_dome.py并手动打断点尝试一下.
    4. 根据下面的提示,自己理一下吧.
      • Flask中的请求响应循环
      • 路由系统
      • 本地上下文
      • 请求与响应对象
      • session
      • 蓝本
      • 模板渲染
  • 相关阅读:
    解决mysql"Access denied for user'root'@'IP地址'"问题
    SpringMVC in IDEA开发实践
    Tomcat安装笔记(on Mac)
    mysql搭建及数据迁移教程
    remove-k-digits
    hdu 4691 Front compression
    STM32的FSMC总线复用调试笔记
    spring AOP 是如何一步一步被简化的
    hdu 2871 Memory Control(伸展树splay tree)
    [置顶] Objective-C ,/,ios,/iphone开发基础:协议(protocol)
  • 原文地址:https://www.cnblogs.com/fengff/p/13498076.html
Copyright © 2020-2023  润新知