Python 工具包 werkzeug 初探
首先,先向大家介绍一下什么是 werkzeug,Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等。
例如我最常用的 Flask 框架就是一 Werkzeug 为基础开发的,这也是我要解析一下 Werkzeug 底层的原因,因为我想知道 Flask 的实现逻辑以及底层控制。这篇文章没有涉及到 Flask 的相关内容,只是以 Werkzeug 创建一个简单的 Web 应用,然后以这个 Web 应用为例剖析请求的处理以及响应的产生过程。
下面我们以一个简短的例子开始,先看看怎么使用 werkzeug,然后再逐步刨析 werkzeug 的实现原理。
安装 werkzeug
我希望读者是在 virtualenv 环境中跟着我的步伐走得,如果你还不知道什么是 virtualenv,那么你可以在我的博客中搜索一下 virtualenv,然后先弄好,再继续,因为很可能因为一些库的冲突等问题导致你看不到本文中介绍的东西。
ok,下面开始安装 werkzeug,
1
|
pip install Werkzeug
|
这条命令下去,几秒钟之后你就可以使用 werkzeug 了。
一个简单地 web 服务器
接下来,我们就开始使用 werkzeug 来创建一个简单的 web 服务器,这个服务器就仅仅返回 “Hello Werkzeug”,没有其他内容。
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
|
#!/usr/bin/env python
# encoding: utf-8
import os
from werkzeug.serving import run_simple
from werkzeug.wrappers import Request, Response
from werkzeug.wsgi import SharedDataMiddleware
class Shortly(object):
def dispatch_request(self, request):
return Response('Hello Werkzeug!')
def wsgi_app(self, environ, start_response):
request = Request(environ)
response = self.dispatch_request(request)
return response(environ, start_response)
def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)
def create_app(with_static=True):
app = Shortly()
if with_static:
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/static': os.path.join(os.path.dirname(__file__), 'static')
})
return app
if __name__ == '__main__':
app = create_app()
run_simple('127.0.0.1', 6666, app, use_debugger=True, use_reloader=True)
|
这段代码就实现了我说的功能,那么我们就来看看这段代码是怎么运作的?
首先,一切都回到最开始的地方开始,从 main 开始看起,可以发现 main 是非常简单地,只有一个初始化函数,然后就调用了 werkzeug 的 run_simple 函数。okay,我们可以发现这个 app 其实是一个 Shortly 对象,这个类就只实现了 3 个方法,一个是 dispatch_request, wsig_app, call ,就这么简单了,那我们就知道了,关键的代码都不是这些,应该是 run_simple.
run_simple 解析
okay,我们这个系列博客的目的就是解析 werkzeug 源码,所以拿到 werkzeug 源码肯定是我们必须要做的。所以第一步我们就需要从 github 上将 werkzeug clone 下来:
1
|
git clone https://github.com/mitsuhiko/werkzeug.git
|
然后,我们就找 run_simple 的代码咯
1
|
vim werkzeug/serving.py
|
goto line 559
我们可以看到这个函数的定义,秉着关注重点的原则,我们就忽略条件判断,以一条最简单地路线来看代码,那么这里就假设:
1
2
3
|
use_debugger = False
static_files = False
use_reloader = False
|
OK, 那到这里其实 run_simple 调用的就是 inner 了,那么就来看看 inner 的代码:
1
2
3
4
5
6
7
8
9
10
11
|
646: try:
647: fd = int(os.environ['WERKZEUG_SERVER_FD'])
648: except (LookupError, ValueError):
649: fd = None
650: srv = make_server(hostname, port, application, threaded,
651: processes, request_handler,
652: passthrough_errors, ssl_context,
653: fd=fd)
654: if fd is None:
655: log_startup(srv.socket)
656: srv.serve_forever()
|
忽略 fd,那么剩下一点点了:
1
2
3
4
5
6
|
650: srv = make_server(hostname, port, application, threaded,
651: processes, request_handler,
652: passthrough_errors, ssl_context,
653: fd=fd)
656: srv.serve_forever()
|
好,你应该和我一样有兴致得想知道这个 make_server 里面是什么内容了,我也很期待,那就跟上去看看。
make_server 的代码我就不贴了,还是最简原则,忽略各种条件,那么这里就假设:
1
2
|
threaded = False
processes = 1
|
那么代码也很简单了,就剩下:
1
2
|
546: return BaseWSGIServer(host, port, app, request_handler,
547: passthrough_errors, ssl_context, fd=fd)
|
很好,好不容易跟踪到这,终于上关键了,那就是这个 BaseWSGIServer 了,我们就来看看这个类实现了什么功能。
先看这个类的定义:
1
|
443: class BaseWSGIServer(HTTPServer, object):
|
这个类是继承自 HTTPServer 的,那么我们就有点底了,这差不多到头了,已经和 Python 的 API 碰上了。好,既然是继承自 HTTPServer,那么就把他当做 HTTPServer,然后继续看 run_simple 的代码,我们一路跟踪下来,我们发现了 656 行有一个 srv.serve_forever()
,那么这不就是 HTTPServer 的用法吗? server.serve_forever() 。
okay,到这那么事情已经暂告一段落了,虽然很多事情都还没搞清楚,例如请求是怎么被封装的,响应又在哪里被处理了,例如URL路由之类的怎么操作的。但是,我们已经对 Werkzeug 有一个大概的印象了,知道他低层还是 HTTPServer 实现的,没有太多特殊的自定义协议。在下一章我们会逐步得进行进行更深层次的解密。欢迎继续关注。
Python 工具包 werkzeug 初探的更多相关文章
- Python 装饰器初探
Python 装饰器初探 在谈及Python的时候,装饰器一直就是道绕不过去的坎.面试的时候,也经常会被问及装饰器的相关知识.总感觉自己的理解很浅显,不够深刻.是时候做出改变,对Python的装饰器做 ...
- PyTools-包罗万象的python工具包
PyTools-包罗万象的python工具包 <---点击这里获取代码,欢迎star. 自己平时写的代码都以函数方式封装起来了,方便代码复用. _________ ________ ______ ...
- python安装 werkzeug
1 pip install werkzeug Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库.这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web ...
- 脑成像数据分析:Python工具包
来源:SealHuang 脑成像技术已经成为认知科学和心理学研究领域中一种重要的研究手段,帮助研究者不断深入发掘我们脑中的秘密.伴随着研究的不断深入,各式各样的指标参数和分析方法也不断推陈出新,以迅雷 ...
- 爬虫开发python工具包介绍 (1)
本文来自网易云社区 作者:王涛 本文大纲: 简易介绍今天要讲解的两个爬虫开发的python库 详细介绍 requests库及函数中的各个参数 详细介绍 tornado 中的httpcilent的应用 ...
- python 工具包安装
(1)wxPython是python的常用gui yum install wxPython (2)numpy, scipy是常用的数学处理工具包 yum install scipy
- python 单步调试初探(未完待续)
pdb 调试: import pdb pdb.set_trace() pudb 调试: http://python.jobbole.com/82638/
- python requests 模块初探
现在经常需要在网页中获取相关内容. 其中无非获取网页返回状态,以及查看网页获取的内容几个方面,那么在这方面来看requests可能比urllib2库更简便一些. 比如:先用方法获取网页 r = req ...
- [转] Python的import初探
转载自:http://www.lingcc.com/2011/12/15/11902/#sec-1 日常使用python编程时,为了用某个代码模块,通常需要在代码中先import相应的module.那 ...
随机推荐
- BZOJ 1647 [Usaco2007 Open]Fliptile 翻格子游戏:部分枚举 位运算
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1647 题意: 在一个n*m(1 <= n,m <= 15)的棋盘上,每一个格子 ...
- html5--1.5 文本元素
html5--1.5 文本元素 学习要点: 掌握常用的文本元素 文本元素,就是讲一段文本设置成相匹配的结构和含义 1.b元素: 我的作用就是 加粗文字: 2.br元素: 我的作用就是强制换行: 3.i ...
- 分享知识-快乐自己:什么是MVC
1.什么是mvc: Model View Controller,是模型-视图-控制器的缩写,一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集到一个组件里,在改进和个性 ...
- github添加ssh公钥
使用git作为版本维护工具非常方便,而且一般个人用github作为远端库就够用了.而一般git连接github的方式采用ssh的方法,http的会略微慢一些.所以为了方便一般会在github设置中添加 ...
- Jmeter-聚合报告
线程组右键--添加--监听器--聚合报告 Aggreagete Report:jmeter最常用的一个Listener,“聚合报告”. Label:每个jmeter的element(例如HTTP Re ...
- linux进程学习笔记
学习了linux下的进程,觉得应该整理一下,忘得差不多了,顺便回顾一下. 学而时习之,不亦说乎~~ 进程笔记 ,什么是进程? The Single UNIX Specification, Versio ...
- CodeForces - 592D: Super M(虚树+树的直径)
Ari the monster is not an ordinary monster. She is the hidden identity of Super M, the Byteforces’ s ...
- bootstrap框架日期时间之年月选择及汉化
==>上次介绍了bootstrap框架日期时间 开始日期和结束日期选择 http://www.cnblogs.com/wjqblogs/p/4043198.html 今天又做了个只选择年月的日期 ...
- JSP 使用<%@include%>报Duplicate local variable path 错误 解决方法
错误提示:Multiple annotations found at this line:- Duplicate local variable path- Duplicate local variab ...
- 三 lambda表达式有什么用
(转载: https://mp.weixin.qq.com/s/-PHOc6p-qKJBktle28AUgA) 一: 直接把代码块赋值给变量 我们知道,对于一个Java变量,我们可以赋给其一个“值”. ...