全文基于Python 2.7 macOS 10.12.2
werkzeug是Python实现的WSGI规范的使用函数库。什么是WSGI?如何理解CGI,WSGI 网上的说明很多,在文章的开始,我想要强调两点
- WSGI是一种服务器和客户端交互的接口规范
- 理解web组件:client, server, and middleware.
正如werkzeug官网Werkzeug上所说,werkzeug使用起来非常简单,但是却非常强大。关于使用简单的这个特性,官网给了一段示例代码。
from werkzeug.wrappers import Request, Response @Request.application def application(request): return Response('Hello World!') if __name__ == '__main__': from werkzeug.serving import run_simple run_simple('localhost', 4000, application)
运行起来以后,打开我们的浏览器输入127.0.0.1:4000就可以看到
一个web应用的本质,实际就是:
浏览器(client)发送一个请求(request) ——> 服务器(server)接收到请求 ——> 服务器处理请求 ——> 返回处理的结果(response) ——> 浏览器处理返回的结果,显示出来。
再看这段代码,开始的func application(),非常的容易理解。函数在server端,接收了来自client的一个request,经过内部的处理以后返回了一个response。但是如果看过其他WSGI教程(比如wsgi接口)的朋友应该会感觉到奇怪,这个函数和别的地方举例的不太一样,因为WSGI要求web开发者必须实现的函数是这个样子的
def application(environ, start_response): response_body = "<h1>Hello World</h1>" header = [('Content-Type', 'text/html')] status = "200 OK" start_response(status, header) print "environ http request method:"+environ['REQUEST_METHOD'] return [response_body]
我们的函数必须接受两个参数environ,start_response。environ是一个保存了请求的各项信息的字典,而start_response是一个func,我们可以用它来给client端返回状态码和response headers。最后return我们真正想要返回的数据。但是werkzeug的这段示例代码却简化了很多,原因就在这个函数的装饰器上 **@Request.application **
@classmethod def application(cls, f): """Decorate a function as responder that accepts the request as first argument. This works like the :func:`responder` decorator but the function is passed the request object as first argument and the request object will be closed automatically:: @Request.application def my_wsgi_app(request): return Response('Hello World!') As of Werkzeug 0.14 HTTP exceptions are automatically caught and converted to responses instead of failing. :param f: the WSGI callable to decorate :return: a new WSGI callable """ #: return a callable that wraps the -2nd argument with the request #: and calls the function with all the arguments up to that one and #: the request. The return value is then called with the latest #: two arguments. This makes it possible to use this decorator for #: both methods and standalone WSGI functions. from werkzeug.exceptions import HTTPException def application(*args): request = cls(args[-2]) with request: try: resp = f(*args[:-2] + (request,)) except HTTPException as e: resp = e.get_response(args[-2]) return resp(*args[-2:]) return update_wrapper(application, f)