IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Flask接收请求的流程 -> 正文阅读

[Python知识库]Flask接收请求的流程

Flask接收请求的流程

Flask是基于werkzeug包实现的。

来研究一下,request是如何通过werkzeug传递给Flask的。

同时研究一下BaseServerserve_forever

BaseWSGIServer

BaseWSGIServerwerkzeug的一个类,继承了HTTPServer
class BaseWSGIServer(HTTPServer)

首先查看构造函数

BaseWSGIServer__init__

    def __init__(
        self,
        host: str,
        port: int,
        app: "WSGIApplication",
        handler: t.Optional[t.Type[WSGIRequestHandler]] = None,
        passthrough_errors: bool = False,
        ssl_context: t.Optional[_TSSLContextArg] = None,
        fd: t.Optional[int] = None,
    ) -> None:
        # 默认
        if handler is None:
            handler = WSGIRequestHandler
        ...# 初始化

        super().__init__(server_address, handler)  # type: ignore

        self.app = app
        self.passthrough_errors = passthrough_errors
        self.shutdown_signal = False
        self.host = host
        self.port = self.socket.getsockname()[1]
		# 初始化
        ...

    def log(self, type: str, message: str, *args: t.Any) -> None:
        _log(type, message, *args)

    def serve_forever(self, poll_interval: float = 0.5) -> None:
        self.shutdown_signal = False
        try:
            super().serve_forever(poll_interval=poll_interval)
        except KeyboardInterrupt:
            pass
        finally:
            self.server_close()

    def handle_error(self, request: t.Any, client_address: t.Tuple[str, int]) -> None:
        if self.passthrough_errors:
            raise

        return super().handle_error(request, client_address)

BaseWSGIServerserve_forever

    def serve_forever(self, poll_interval: float = 0.5) -> None:
        self.shutdown_signal = False
        try:
            # 调用父类的serve_forever,即BaseServer.serve_forever
            super().serve_forever(poll_interval=poll_interval)
        except KeyboardInterrupt:
            pass
        finally:
            self.server_close()

BaseServer.serve_forever

    def serve_forever(self, poll_interval=0.5):
        self.__is_shut_down.clear()
        try:
            with _ServerSelector() as selector:
                selector.register(self, selectors.EVENT_READ)

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                    if ready:
                        self._handle_request_noblock() # 这一步是工作语句。跟踪

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

BaseServer._handle_request_noblock

class BaseServer: 
    
    ...
    def __init__(self, server_address, RequestHandlerClass):
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False
    ...
    
    def _handle_request_noblock(self):
        try:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)  # 处理request
            except Exception:
                self.handle_error(request, client_address)
                self.shutdown_request(request) # 关闭request
            except:
                self.shutdown_request(request)
                raise
        else:
            self.shutdown_request(request)
            
    def process_request(self, request, client_address):
        self.finish_request(request, client_address) # 调用finish_request
        self.shutdown_request(request)
        
    def finish_request(self, request, client_address):
        # 最重要的一步。
        # 这里的RequestHandlerClass在Flask中默认是WSGIRequestHandler
        # 传递的值分别是request请求, client_address地址和self(即BaseWSGIServer实例)
        self.RequestHandlerClass(request, client_address, self) 

    def shutdown_request(self, request):
        self.close_request(request)

WSGIRequestHandler

WSGIRequestHandler没有__init__函数,跟踪父类**BaseRequestHandler**

# 根据名字知道这是一个基类。
class BaseRequestHandler:

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server # 
        self.setup()
        try:
            # 最重要的一步,调用了WSGIRequestHandler.handle函数。
            self.handle() 
        finally:
            self.finish()

    def setup(self):
        pass

    def handle(self):
        pass

    def finish(self):
        pass

werkzeug包中,WSGIRequestHandler继承了BaseRequestHandler,也就是调用WSGIRequestHandler.handle()

WSGIRequestHandler.handle()

    def handle(self) -> None:
        """Handles a request ignoring dropped connections."""
        try:
            # 这里的self是WSGIRequestHandler实例,跟进
            BaseHTTPRequestHandler.handle(self) 
        except (ConnectionError, socket.timeout) as e:
            self.connection_dropped(e)
        except Exception as e:
            if self.server.ssl_context is not None and is_ssl_error(e):
                self.log_error("SSL error occurred: %s", e)
            else:
                raise
        if self.server.shutdown_signal:
            self.initiate_shutdown()

BaseHTTPRequestHandler.handle(self)

    def handle(self):
        # 这里的self是WSGIRequestHandler实例
        """Handle multiple requests if necessary."""
        self.close_connection = True

        self.handle_one_request()# 处理一个request,跟进该函数
        while not self.close_connection:
            self.handle_one_request()

WSGIRequestHandler.handle_one_request()

    def handle_one_request(self) -> None:
        """Handle a single HTTP request."""
        self.raw_requestline = self.rfile.readline()
        if not self.raw_requestline:
            self.close_connection = True
        elif self.parse_request():
            self.run_wsgi() # 终于到了run_wsgi

run_wsgi

    def run_wsgi(self) -> None:
        if self.headers.get("Expect", "").lower().strip() == "100-continue":
            self.wfile.write(b"HTTP/1.1 100 Continue\r\n\r\n")

        self.environ = environ = self.make_environ()
        status_set: t.Optional[str] = None
        headers_set: t.Optional[t.List[t.Tuple[str, str]]] = None
        status_sent: t.Optional[str] = None
        headers_sent: t.Optional[t.List[t.Tuple[str, str]]] = None

        def write(data: bytes) -> None:
            ...# 往socket中写入response
            self.wfile.write(data)
            self.wfile.flush()

        def start_response(status, headers, exc_info=None):  # type: ignore
            nonlocal status_set, headers_set
            if exc_info:
                try:
                    if headers_sent:
                        raise exc_info[1].with_traceback(exc_info[2])
                finally:
                    exc_info = None
            elif headers_set:
                raise AssertionError("Headers already set")
            status_set = status
            headers_set = headers
            return write

        def execute(app: "WSGIApplication") -> None:
            # 调用Flask.__call__(self, environ, start_response)
            application_iter = app(environ, start_response)
            try:
                for data in application_iter:
                    write(data)
                if not headers_sent:
                    write(b"")
            finally:
                if hasattr(application_iter, "close"):
                    application_iter.close()  # type: ignore

        try:
            execute(self.server.app) # self.server.app就是Flask的实例
        except (ConnectionError, socket.timeout) as e:
            self.connection_dropped(e, environ)
        except ...
        ...

总结

总的来说就是通过使用werkzeug来代理一个Server,使用WSGIRequestHandler调用到Flask.__call__函数,然后获取返回值,再通过socket返回到客户端。

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章           查看所有文章
加:2021-08-05 17:18:30  更:2021-08-05 17:21:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 7:13:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码