Flask源码分析
功夫小熊猫 人气:0
首先,推荐一个便宜的云主机,感觉比阿里便宜,新用户一年68元,滴滴云
附上活动链接:https://i.didiyun.com/2d7Jy4Nzle8
Flask的最小应用程序如下:
```python
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()方法
```python
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,
```
```python
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。
```python
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。
```python
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的数据请求和发送。
```python
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()
```python
def serve_forever(self):
self.shutdown_signal = False
try:
HTTPServer.serve_forever(self)
except KeyboardInterrupt:
pass
finally:
self.server_close()
```
为了更好的说明,把WSGIRequestHandler和BaseWSGIServer继承过来,单独运行获得http的响应。
```python
from werkzeug.serving import WSGIRequestHandler,BaseWSGIServer
class New_Handler(WSGIRequestHandler):
page = '''\
hello
''' 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() ``` ![](https://img2020.cnblogs.com/blog/1639143/202003/1639143-20200308151037279-988954675.jpg) 既然http的请求响应入口已经找到了,那么就来看看请求路由的处理,所以要研究装饰器@app.route('/'),来看看Flask中路由处理思路。 装饰器如下: ```python 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()。加载全部内容