当前位置: 首页 > 工具软件 > Werkzeug > 使用案例 >

初窥werkzeug

宗政文彬
2023-12-01

初窥werkzeug

什么是werkzeug

首先要明确一点werkzeug不是一个WEB服务器也不是一个WEB框架, 它是一个WSGI的工具包, 它可以作为一个WEB框架的底层库被使用, 而Flask框架就是以werkzeug为基础开发的。作为WSGI的工具包, 一个WEB框架的底层库, 它封装了很多有关于WEB框架的东西, 比如Request, Response等。如果想要了解Flask的底层原理, 那么势必要剖析werkzeug的实现原理。

安装werkzeug

创建虚拟环境

创建虚拟环境的目的是为了避免模块之间的冲突, 也是为了一个干净高效的环境。

# 创建虚拟环境
mkvirtualenv -p python3.8 my_werkzeug
安装werkzeug
pip install werkzeug

自己写一个Easy_WebServer

接下来就基于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为基础实现的。

 类似资料: