Flask源码解析之启动流程 1. 最小的 Flask 程序 1 2 3 4 5 6 7 8 9 10 11 12 13 from flask import Flask app = Flask(__name__) @app.route("/" ) def hello_world (): return "<p>Hello, World!</p>" if __name__ == '__main__' : app.run()
我们先从使用代码启动的方式来看, 暂时不看使用命令行的方式启动的过程。
我们安装代码的执行顺序从上往下看
①第一步 导入Flask
对象。
②实例化app
对象。在内部执行类的__init__
方法。
③创建路由和视图函数。
④执行 app.run()
。
2. 查看 app 源码 我们进入app
的源码中查看__init__
发生了什么(其他的一些类属性先不管)。
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 29 30 31 32 33 34 35 36 37 38 39 class Flask (App ): def __init__ ( self, import_name: str , static_url_path: str | None = None , static_folder: str | os.PathLike | None = "static" , static_host: str | None = None , host_matching: bool = False , subdomain_matching: bool = False , template_folder: str | os.PathLike | None = "templates" , instance_path: str | None = None , instance_relative_config: bool = False , root_path: str | None = None , ): super ().__init__( import_name=import_name, static_url_path=static_url_path, static_folder=static_folder, static_host=static_host, host_matching=host_matching, subdomain_matching=subdomain_matching, template_folder=template_folder, instance_path=instance_path, instance_relative_config=instance_relative_config, root_path=root_path, ) if self.has_static_folder: assert ( bool (static_host) == host_matching ), "Invalid static_host/host_matching combination" self_ref = weakref.ref(self) self.add_url_rule( f"{self.static_url_path} /<path:filename>" , endpoint="static" , host=static_host, view_func=lambda **kw: self_ref().send_static_file(**kw), )
在①处Flask
设置了静态文件默认路径和模板文件的路径。
在②处执行了父类的init
文件。
在③的地方添加了静态文件的路由, 所以Flask
在初始化的时候,我们不指定配置文件时,会有默认的路由创建。
3. 我们再看 app.run()的方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Flask (App ): def run ( self, host: str | None = None , port: int | None = None , debug: bool | None = None , load_dotenv: bool = True , **options: t.Any, ) -> None : “”“ 本地开发的启动方式, 不要再生产服务器使用的一些注意事项 ”“” from werkzeug.serving import run_simple try : run_simple(t.cast(str , host), port, self, **options) finally : self._got_first_request = False
在①的上面都是针对host
、port
以及环境变量的的一些配置。run
方法中真正执行的是werkzeug
的run_simple
方法。他接受了一个host
参数,一个port
参数,和一个self
, 这个self
就是Flask
本身的实例。
4. run_simple 的源码。 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 def run_simple ( hostname: str , port: int , application: WSGIApplication, use_reloader: bool = False , use_debugger: bool = False , use_evalex: bool = True , extra_files: t.Iterable[str ] | None = None , exclude_patterns: t.Iterable[str ] | None = None , reloader_interval: int = 1 , reloader_type: str = "auto" , threaded: bool = False , processes: int = 1 , request_handler: type [WSGIRequestHandler] | None = None , static_files: dict [str , str | tuple [str , str ]] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , ) -> None : """ 在内部启动了WSGI服务器, 即socket服务, 然后等待用户访问具体的路由。 """ if not isinstance (port, int ): raise TypeError("port must be an integer" ) if static_files: from .middleware.shared_data import SharedDataMiddleware application = SharedDataMiddleware(application, static_files) if use_debugger: from .debug import DebuggedApplication application = DebuggedApplication(application, evalex=use_evalex) if not is_running_from_reloader(): fd = None else : fd = int (os.environ["WERKZEUG_SERVER_FD" ]) srv = make_server( hostname, port, application, threaded, processes, request_handler, passthrough_errors, ssl_context, fd=fd, ) srv.socket.set_inheritable(True ) os.environ["WERKZEUG_SERVER_FD" ] = str (srv.fileno()) if not is_running_from_reloader(): srv.log_startup() _log("info" , _ansi_style("Press CTRL+C to quit" , "yellow" )) if use_reloader: from ._reloader import run_with_reloader try : run_with_reloader( srv.serve_forever, extra_files=extra_files, exclude_patterns=exclude_patterns, interval=reloader_interval, reloader_type=reloader_type, ) finally : srv.server_close() else : srv.serve_forever()
在①处滴调用make_server
方法返回了实例化后的WSGI
服务对象,并在②处调用serve_forever
方法,启动服务等待接受请求。而WSGI
对象内部实现了一个socket
服务,他继承了HTTPServer
,HTTPServer
又继承了socketserver.TCPServer
。
5. make_server 不考虑其他的情况,我们看到返回了一个实例化的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def make_server ( host: str , port: int , app: WSGIApplication, threaded: bool = False , processes: int = 1 , request_handler: type [WSGIRequestHandler] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , fd: int | None = None , ) -> BaseWSGIServer: return BaseWSGIServer( host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd )
其实到这里Flask
启动的流程已经大致结束了,但是我们可以结合上一篇文章《Flask源码解析之路由》来看看一个路由到来的整个流程。
6. 整个服务启动请求流程 6.1前置知识 6.1.1 TCP 服务的执行流程 我们可以通过查看Python
的文档,去看看如何实现一个TCPServer
。
在启动一个TCPServer
的时候他接受一个继承BaseHTTPRequestHandler的Handler
对象,然后当请求到来的时候执行内部的handle
方法。具体的TCPServer
执行流程大致如下:
6.1.2 with语句 通过with
语句创建tcp
对象,初始化一些参数,创建socket
对象,绑定地址和开启监听。
1 2 3 4 5 6 7 8 9 10 11 12 class TCPServer (BaseServer ): def __init__ (self, server_address, RequestHandlerClass, bind_and_activate=True ): BaseServer.__init__(self, server_address, RequestHandlerClass) self.server_bind() self.server_activate() def server_bind (self ): ... def server_activate (self ): ...
6.1.3 serve_forever 方法 父类的with
语句__enter__
方法返回self
, 调用self.serve_forever
方法,TCPServer
未实现所以查找BaseServer
的serve_forever
方法。
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 class BaseServer : def __init__ (self, server_address, RequestHandlerClass ): """Constructor. May be extended, do not override.""" self.server_address = server_address self.RequestHandlerClass = RequestHandlerClass self.__is_shut_down = threading.Event() self.__shutdown_request = False 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) if self.__shutdown_request: break if ready: self._handle_request_noblock() self.service_actions() finally : self.__shutdown_request = False self.__is_shut_down.set ()
6.1.4 _handle_request_noblock 方法 在serve_forever
中执行了_handle_request_noblock
方法获取请求。
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 29 30 31 class BaseServer : 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) except Exception: self.handle_error(request, client_address) self.shutdown_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) self.shutdown_request(request) def finish_request (self, request, client_address ): self.RequestHandlerClass(request, client_address, self)
6.1.5 RequestHandlerClass 接下来我们再看TCPServer
中的RequestHandlerClass
是如何实现的。在上面Python
官方文档示例中:TCPServer
自定义了一个MyTCPHandler
他继承了socketserver.BaseRequestHandler
。我们查看这个类的实现方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class BaseRequestHandler : “”“ 这个类是为要处理的每个请求实例化的。构造函数设置实例变量request、client_address server,然后调用handle()方法。要实现一个特定的服务,您所需要做的就是派生一个定义 handle()方法的类。 “”“ def __init__ (self, request, client_address, server ): self.request = request self.client_address = client_address self.server = server self.setup() try : self.handle 方法() finally : self.finish() def setup (self ): pass def handle (self ): pass def finish (self ): pass
我们可以根据注释了解到,他是一个专门处理请求类的基类,我们要自定义TCPServcer
,就要继承他实现一个子类。在他的init
方法中调用handle
方法。
这下我们终于知道了为什么我们自己写一个TCPServer
时,为什么要自己实现一个Handler
类,且要实现handle
方法了。
7. WSGIRequestHandler 让我们再回到Flask
的源码中,在BaseWSGIServer
中同样有属性是handle
, 他的的类型是,WSGIRequestHandler
。但是他不是直接继承socketserver.BaseRequestHandler
而是socketserver.StreamRequestHandler
, 其实也是一样的,只不过StreamRequestHandler
在对BaseRequestHandler
封装了一层而已。接下来我们看WSGIRequestHandler
的源码。
1 2 3 4 5 6 7 8 9 10 11 12 class WSGIRequestHandler (BaseHTTPRequestHandler ): def handle (self ) -> None : try : super ().handle() 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
在handle
中调用了父类的handle
方法,我们再看父类的handle
方法。执行了handle_one_request
方法。
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class BaseHTTPRequestHandler (socketserver.StreamRequestHandler ): def handle_one_request (self ): try : self.raw_requestline = self.rfile.readline(65537 ) if len (self.raw_requestline) > 65536 : self.requestline = '' self.request_version = '' self.command = '' self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG) return if not self.raw_requestline: self.close_connection = True return if not self.parse_request(): return mname = 'do_' + self.command if not hasattr (self, mname): self.send_error( HTTPStatus.NOT_IMPLEMENTED, "Unsupported method (%r)" % self.command) return method = getattr (self, mname) method() self.wfile.flush() except TimeoutError as e: self.log_error("Request timed out: %r" , e) self.close_connection = True return def handle (self ): """Handle multiple requests if necessary.""" self.close_connection = True self.handle_one_request() while not self.close_connection: self.handle_one_request()
7.1 _getattr_ 方法 此方法中重要的一段代码是执行了method
方法。这个方法是通过getattr
获取的。 getattr
方法会执行 类中的__getattr__
方法。
1 2 3 4 5 6 7 8 class WSGIRequestHandler (BaseHTTPRequestHandler ): def __getattr__ (self, name: str ) -> t.Any: if name.startswith("do_" ): return self.run_wsgi return getattr (super (), name)
7.2 run_wsgi 方法 它又调用了run_wsgi
方法,再看run_wsgi
的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class WSGIRequestHandler (BaseHTTPRequestHandler ): def run_wsgi (self ) -> None : def execute (app: WSGIApplication ) -> None : application_iter = app(environ, start_response) try : execute(self.server.app) except (ConnectionError, socket.timeout) as e: self.connection_dropped(e, environ) except Exception as e:
7.3 execute方法 在run_wsgi
方法中最终执行了execute
方法,它接受了一个参数self.server.app
, 我可以先看看这个self.server.app
参数是谁。
1 2 3 4 class WSGIRequestHandler (BaseHTTPRequestHandler ): def execute (app: WSGIApplication ) -> None : application_iter = app(environ, start_response)
7.4 excute 的参数 self.server.app 我们先回到【6.1.4 _handle_request_noblock 方法】步骤, 在finish_request
方法中实例化了self.RequestHandlerClass(request, client_address, self)
这个 RequestHandlerClass
也就是我们现在看到的 WSGIRequestHandler
,但是他没有初始化的步骤,所以是继承了基类的初始化方法。我们看代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class BaseRequestHandler : def __init__ (self, request, client_address, server ): self.request = request self.client_address = client_address self.server = server self.setup() try : self.handle() finally : self.finish() class StreamRequestHandler (BaseRequestHandler ): ... class BaseHTTPRequestHandler (socketserver.StreamRequestHandler ): ... class WSGIRequestHandler (BaseHTTPRequestHandler ): ...
这里的self.server
正是BaseServer
类或者是他的子类。self.server.app
正是BaseServer
的app
属性。
我们再回到 第四步run_simple
的源码中,它调用了make_server
方法 创建了BaseWSGIServer
实例,所以上面的这句话【 这里的self.server
正是BaseServer
类或者是他的子类】中指的类
就是BaseWSGIServer
这个类。 我们看代码:
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 class BaseServer : ... class TCPServer (BaseServer ): ... class HTTPServer (TCPServer ): ... class BaseWSGIServer (HTTPServer ): def __init__ ( self, host: str , port: int , app: WSGIApplication, handler: type [WSGIRequestHandler] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , fd: int | None = None , ) -> None : if handler is None : handler = WSGIRequestHandler self.app = app
所以self.server.app
指的就是BaseWSGIServer
中初始化传过来的app
实参。 那app
是谁呢, 就很显而易见了。
是由run_simple(hostname, port, application,...) --> make_server(hostname, port, application,...) --> BaseWSGIServer(hostname, port, application,...)
一步一步传过来的。
run_simple
又是在Flask
的run
方法中调用的, 第三个参数正是self
,即Flask
实例对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Flask (App ): def run ( self, host: str | None = None , port: int | None = None , debug: bool | None = None , load_dotenv: bool = True , **options: t.Any, ) -> None : from werkzeug.serving import run_simple try : run_simple(t.cast(str , host), port, self, **options) finally : self._got_first_request = False
所以excute
的参数self.server.app
正是Flask
实例对象。
我们再回到 【7.3 execute方法】,在其内部执行了app(environ, start_response)
, 也就是执行了:
1 2 flask_obj = Flask() flask_obj()
当我们调用实例对象的方法时, 其实是执行了类的__call__
方法。
8. Flask 的 _call_ 方法
所以当前一个请求过来,执行了WSGIRequestHandler
的handle
方法,handle
方法又经过七拐八拐回到了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 29 30 class Flask (App ): def wsgi_app (self, environ: dict , start_response: t.Callable ) -> t.Any: ctx = self.request_context(environ) error: BaseException | None = None try : try : ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except : error = sys.exc_info()[1 ] raise return response(environ, start_response) finally : if "werkzeug.debug.preserve_context" in environ: environ["werkzeug.debug.preserve_context" ](_cv_app.get()) environ["werkzeug.debug.preserve_context" ](_cv_request.get()) if error is not None and self.should_ignore_error(error): error = None ctx.pop(error) def __call__ (self, environ: dict , start_response: t.Callable ) -> t.Any: return self.wsgi_app(environ, start_response)
接下来就按照self.full_dispatch_request()
的请求进行执行,
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 class Flask (App ): def dispatch_request (): """ 执行视图函数 """ req = request_ctx.request if req.routing_exception is not None : self.raise_routing_exception(req) rule: Rule = req.url_rule if ( getattr (rule, "provide_automatic_options" , False ) and req.method == "OPTIONS" ): return self.make_default_options_response() view_args: dict [str , t.Any] = req.view_args return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) def preprocess_request (self ) -> ft.ResponseReturnValue | None : """ 在请求之前调用,如果有 brfore_request 中间件,则直接调用,如果不返回None, 则直接返 回,不走具体的视图方法。 """ names = (None , *reversed (request.blueprints)) for name in names: if name in self.url_value_preprocessors: for url_func in self.url_value_preprocessors[name]: url_func(request.endpoint, request.view_args) for name in names: if name in self.before_request_funcs: for before_func in self.before_request_funcs[name]: rv = self.ensure_sync(before_func)() if rv is not None : return rv return None def full_dispatch_request (self ) -> Response: """ 完整的请求执行流程。 """ self._got_first_request = True try : request_started.send(self, _async_wrapper=self.ensure_sync) rv = self.preprocess_request() if rv is None : rv = self.dispatch_request() except Exception as e: rv = self.handle_user_exception(e) return self.finalize_request(rv)
总的来说,Flask
的请求逻辑是由werkzeug
处理sockrt
底层逻辑, 由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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 class Flask (App ): def run ( self, host: str | None = None , port: int | None = None , debug: bool | None = None , load_dotenv: bool = True , **options: t.Any, ) -> None : """ 1 ===> 服务启动执行 run 方法, 然后调用 werkzeug 的 run_simple 方法。 """ from werkzeug.serving import run_simple run_simple(t.cast(str , host), port, self, **options) def dispatch_request (self ) -> ft.ResponseReturnValue: view_args: dict [str , t.Any] = req.view_args return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) def full_dispatch_request (self ) -> Response: self._got_first_request = True try : rv = self.preprocess_request() if rv is None : rv = self.dispatch_request() except Exception as e: rv = self.handle_user_exception(e) return self.finalize_request(rv) def wsgi_app (self, environ: dict , start_response: t.Callable ) -> t.Any: """ ===> 6.1 执行具体的请求逻辑。 """ ctx = self.request_context(environ) try : ctx.push() response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except : error = sys.exc_info()[1 ] raise return response(environ, start_response) def __call__ (self, environ: dict , start_response: t.Callable ) -> t.Any: """ ===> 6 调用 wsgi_app 方法 """ return self.wsgi_app(environ, start_response)
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def make_server ( host: str , port: int , app: WSGIApplication, threaded: bool = False , processes: int = 1 , request_handler: type [WSGIRequestHandler] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , fd: int | None = None , ) -> BaseWSGIServer: return BaseWSGIServer( host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd ) def run_simple ( hostname: str , port: int , application: WSGIApplication, use_reloader: bool = False , use_debugger: bool = False , use_evalex: bool = True , extra_files: t.Iterable[str ] | None = None , exclude_patterns: t.Iterable[str ] | None = None , reloader_interval: int = 1 , reloader_type: str = "auto" , threaded: bool = False , processes: int = 1 , request_handler: type [WSGIRequestHandler] | None = None , static_files: dict [str , str | tuple [str , str ]] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , ) -> None : srv = make_server( hostname, port, application, threaded, processes, request_handler, passthrough_errors, ssl_context, fd=fd, ) srv.serve_forever()
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 class BaseServer : """ BaseWSGIServer 类的基类 """ def __init__ (self, server_address, RequestHandlerClass ): self.RequestHandlerClass = RequestHandlerClass def serve_forever (self, poll_interval=0.5 ): self.__is_shut_down.clear() with _ServerSelector() as selector: selector.register(self, selectors.EVENT_READ) while not self.__shutdown_request: ready = selector.select(poll_interval) if self.__shutdown_request: break if ready: self._handle_request_noblock() self.service_actions() def _handle_request_noblock (self ): try : request, client_address = self.get_request() except OSError: return if self.verify_request(request, client_address): self.process_request(request, client_address) def process_request (self, request, client_address ): self.finish_request(request, client_address) self.shutdown_request(request) def finish_request (self, request, client_address ): self.RequestHandlerClass(request, client_address, self) def __enter__ (self ): return self def __exit__ (self, *args ): self.server_close() class TCPServer (BaseServer ): def __init__ (self, server_address, RequestHandlerClass, bind_and_activate=True ): """Constructor. May be extended, do not override.""" BaseServer.__init__(self, server_address, RequestHandlerClass) self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try : self.server_bind() self.server_activate() except : self.server_close() raise def server_activate (self ): self.socket.listen(self.request_queue_size) def get_request (self ): return self.socket.accept() class HTTPServer (socketserver.TCPServer ): def server_bind (self ): socketserver.TCPServer.server_bind(self) host, port = self.server_address[:2 ] self.server_name = socket.getfqdn(host) self.server_port = port class BaseWSGIServer (HTTPServer ): def __init__ ( self, host: str , port: int , app: WSGIApplication, handler: type [WSGIRequestHandler] | None = None , passthrough_errors: bool = False , ssl_context: _TSSLContextArg | None = None , fd: int | None = None , ) -> None : if handler is None : handler = WSGIRequestHandler self.app = app super ().__init__( server_address, handler, bind_and_activate=False , )
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 class BaseRequestHandler : """ 请求处理类基类 """ def __init__ (self, request, client_address, server ): self.request = request self.client_address = client_address self.server = server self.setup() try : self.handle() finally : self.finish() def handle (self ): pass class StreamRequestHandler (BaseRequestHandler ): ... class BaseHTTPRequestHandler (socketserver.StreamRequestHandler ): """ 请求处理基类,该类的注释详细的说明了作者解析HTTP协议的标准。具体课参阅源码。 """ def parse_request (self ): """ 解析 HTTP 请求,得到请求方法 GET 或者 POST 等 """ self.command = None command, path = words[:2 ] self.command, self.path = command, path return True def handle_one_request (self ): """ 处理某一个请求 """ try : mname = 'do_' + self.command method = getattr (self, mname) method() except TimeoutError as e: return def handle (self ): """Handle multiple requests if necessary.""" self.close_connection = True self.handle_one_request() while not self.close_connection: self.handle_one_request() class WSGIRequestHandler (BaseHTTPRequestHandler ): server: BaseWSGIServer def run_wsgi (self ) -> None : def execute (app: WSGIApplication ) -> None : application_iter = app(environ, start_response) try : execute(self.server.app) except (ConnectionError, socket.timeout) as e: self.connection_dropped(e, environ) except Exception as e: if self.server.passthrough_errors: raise if status_sent is not None and chunk_response: self.close_connection = True try : if status_sent is None : status_set = None headers_set = None execute(InternalServerError()) except Exception: pass from .debug.tbtools import DebugTraceback msg = DebugTraceback(e).render_traceback_text() self.server.log("error" , f"Error on request:\n{msg} " ) def handle (self ) -> None : super ().handle() def __getattr__ (self, name: str ) -> t.Any: if name.startswith("do_" ): return self.run_wsgi return getattr (super (), name)