Flask源码分析
首先,推荐一个便宜的云主机,感觉比阿里便宜,新用户一年68元,滴滴云
附上活动链接:https://i.didiyun.com/2d7Jy4Nzle8
Flask的最小应用程序如下:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
app.run()
Flask的类从flask包中引入后,直接制造app实例,使用app实例执行run方法。
所以先来看看Flask类中的_init__()和run()方法
def __init__(
# 这里用的比较多的是,static_folder,static_url_path静态目录的指定,实例中都是默认参数
self,
import_name,
static_url_path=None,
static_folder="static",
static_host=None,
host_matching=False,
subdomain_matching=False,
template_folder="templates",
instance_path=None,
instance_relative_config=False,
root_path=None,
def run(self, host=None, port=None, debug=None, load_dotenv=True, **options):
try:
run_simple(host, port, self, **options)
finally:
self._got_first_request = False
run方法中省略调试相关的代码,关键执行代码是run_simple方法,带入默认的host和port以及对象,host为127.0.0.1,port为5000。那么就来分析run_simple()
run_simple()
run_simple方法来自werkzeug中的serving.py。
def run_simple(
hostname,
port,
application
):
def inner():
try:
fd = int(os.environ["WERKZEUG_SERVER_FD"])
except (LookupError, ValueError):
fd = None
srv = make_server(
hostname,
port,
application,
threaded,
processes,
request_handler,
passthrough_errors,
ssl_context,
fd=fd,
)
if fd is None:
log_startup(srv.socket)
srv.serve_forever()
inner()
run_simple()主要是执行了inner(),inner中初始化srv实例后执行srv.serve_forever()方法。先看make_server()方法,根据进程和线程使用不同的类进行初始化,且这些类都继承了BaseWSGIServer。
def make_server(
host=None,
port=None,
app=None,
threaded=False,
processes=1,
request_handler=None,
passthrough_errors=False,
ssl_context=None, fd=None,):
if threaded and processes > 1:
raise ValueError("cannot have a multithreaded and multi process server.")
elif threaded:
return ThreadedWSGIServer(省略 )
elif processes > 1:
return ForkingWSGIServer(省略 )
else:
return BaseWSGIServer(省略 )
这里以BaseWSGIServer为例进行分析。BaseWSGIServer继承HTTPServer,这里带入的参数除了host,port还有handler,sWSGIRequestHandler,WSGIRequestHandler继承BaseHTTPRequestHandler。主要是为了实现http的数据请求和发送。
class BaseWSGIServer(HTTPServer, object): """Simple single-threaded, single-process WSGI server."""
multithread = False
multiprocess = False
def __init__(
self,
host,
port,
app,
handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,):
if handler is None:
handler = WSGIRequestHandler
先看一下执行函数,serve_forever,执行的是 HTTPServer.serve_forever()
def serve_forever(self):
self.shutdown_signal = False
try:
HTTPServer.serve_forever(self)
except KeyboardInterrupt:
pass
finally:
self.server_close()
为了更好的说明,把WSGIRequestHandler和BaseWSGIServer继承过来,单独运行获得http的响应。
from werkzeug.serving import WSGIRequestHandler,BaseWSGIServer
class New_Handler(WSGIRequestHandler):
page = '''\
<html>
<body>
<p>hello</p>
</body>
</html>
'''
def do_GET(self):
current_path = self.path
# self.send_error(415,'your url is %s' % current_path)
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.send_header("Content-Length", 100)
self.end_headers()
self.wfile.write(self.page.encode('utf-8'))
tcp_server = BaseWSGIServer(host="127.0.0.1",port=5000,app=None,handler=New_Handler)
if __name__ == "__main__":
tcp_server.serve_forever()
既然http的请求响应入口已经找到了,那么就来看看请求路由的处理,所以要研究装饰器@app.route(‘/’),来看看Flask中路由处理思路。
装饰器如下:
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
# 路由装饰器的使用
@app.route('/')
def hello_world():
return "hello_world"
以简单根目录请求为例,通过装饰器可以看出,首先执行self.add_url_rule(rule, endpoint, f, **options),然后再执行实例方法hello_world()。