首先要明确一点werkzeug不是一个WEB服务器也不是一个WEB框架, 它是一个WSGI的工具包, 它可以作为一个WEB框架的底层库被使用, 而Flask框架就是以werkzeug为基础开发的。作为WSGI的工具包, 一个WEB框架的底层库, 它封装了很多有关于WEB框架的东西, 比如Request, Response等。如果想要了解Flask的底层原理, 那么势必要剖析werkzeug的实现原理。
创建虚拟环境的目的是为了避免模块之间的冲突, 也是为了一个干净高效的环境。
# 创建虚拟环境
mkvirtualenv -p python3.8 my_werkzeug
pip install werkzeug
接下来就基于werkzeug来自己写一个简单的WEB服务器。
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
@Request.application
def hello_world(request):
return Response('Hello World')
if __name__ == '__main__':
run_simple('127.0.0.1', 4000, hello_world)
让我们先忽略Request和Response, 这个简单的Web可以看出, main底下我们只实现了一个方法就是run_simple, 它需要三个参数: host, port, application, 那就点进去看看源码吧。
def run_simple(
hostname,
port,
application,
use_reloader=False,
use_debugger=False,
use_evalex=True,
extra_files=None,
reloader_interval=1,
reloader_type="auto",
threaded=False,
processes=1,
request_handler=None,
static_files=None,
passthrough_errors=False,
ssl_context=None,
):
# 可以看出它除了host, port, application还需要其它参数, 这个我们先不管
再往下看, 忽略一些逻辑判断。
...
def log_startup(sock): # 这明显就是日志相关, 忽略
def inner(): # 正戏来了
我们好好看看inner这个函数。
def inner():
try:
fd = int(os.environ["WERKZEUG_SERVER_FD"])
except (LookupError, ValueError):
fd = None
# 这里又将参数传入给了make_server, 那么就去看看这个make_server
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() # 留意(关注点)
进入到make_server, 看到同样是对这些参数的需要, 与run_simple相似。
def make_server(
host=None,
port=None,
app=None,
threaded=False,
processes=1,
request_handler=None,
passthrough_errors=False,
ssl_context=None,
fd=None,
):
...
else:
return BaseWSGIServer(
host, port, app, request_handler, passthrough_errors, ssl_context, fd=fd
)
再次忽略一些逻辑判断, 最终指向就是BaseWSGIServer, 看到Base这个词就只离目标不远了, 看一看。
class BaseWSGIServer(HTTPServer, object): # HTTPServer
看到HTTPServer, 就明白了一切, 合着整了半天最终是继承了HTTPServer, 也就是说在这里与Python的API接了头, 它的底层是由HTTPServer实现的, 再回看一下上文的一个关注点srv.serve_forever()
, 这不就是HTTPServer的父类TCPServer, 它的父类BaseServer中的serve_forever()
嘛? 这一切就清楚明了了, werkzeug的底层通过HTTPServer与API接头, 而Flask就是以werkzeug为基础实现的。