课程地址:Python 工程师进阶技术图谱
文章目录
- 🌾 Response使用及wsgify装饰器
- 1、Response的使用
- 2、wsgify装饰器
🌾 Response使用及wsgify装饰器
1、Response的使用
前面一节我们知道了,使用webob的Request模块可以很方便地对请求进行解析。而接下来要介绍的Response模块,就可以方便地对响应进行封装:
- 帮助调用start_response函数,返回响应头。
- 对响应的正文进行封装。
上述两个操作就可以统一让一个Response类来进行。
def simple_app(environ:dict, start_response):
res = Response()
print(res.status_code)
print(res.status)
print(res.headers) # 一个对象
print(res.headerlist) # 改成list类型而已
res.body = '<h1>day day up!</h1>'.encode()
return res(environ, start_response) # 返回报文的正文部分,即网页内容
上面的代码就可以对请求产生一个规范的响应,不必自己单独调用start_response
函数。用上面的代码替换之前的simple_app
,运行一下:
'''
Serving on port 9000...
200
200 OK
ResponseHeaders([('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0')])
[('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0')]
'''
2、wsgify装饰器
虽然以前有时会用到装饰器,但我一直有些疑惑,装饰器到底是个什么东西,它具体在干啥?后面老师带着看了wsgify的一些源码,就稍微了解一些了。
装饰器,就是对目标进行封装的作用。
我们可以这样使用装饰器:
@wsgify
def app(request:Request) -> Response: # 一个请求对应一个响应
return '<h1>day day up!</h1>'
上面这段代码就可以满足“app”的三个要求:
- 可调用
- 可以接收两个参数(environ和start_response)
- return一个可迭代对象
但是看我们的app函数头def app(request:Request)
,只接受了一个参数;再看返回值,只是一个字符串<h1>day day up!</h1>
,不是“可迭代”的。那么,它如何满足app的三个要求呢?
这就是装饰器的作用了!下面的其实函数app
就作为一个参数,传递给了wsgify这个类(没错,wsgify就是一个类),我们看看这个类中__init__
方法的源码
def __init__(self, func=None, RequestClass=None,
args=(), kwargs=None, middleware_wraps=None):
self.func = func
if (RequestClass is not None
and RequestClass is not self.RequestClass):
self.RequestClass = RequestClass
self.args = tuple(args)
if kwargs is None:
kwargs = {}
self.kwargs = kwargs
self.middleware_wraps = middleware_wraps
我们在@wsgify
下面定义的app
函数,就作为wsgify的func
参数传递进来了,然后我们在代码中调用函数app
时,实际调用的是wsgify这个类,而我们定义的app函数只是作为这个类的一个参数。
想要更多地了解@wsgify,可以阅读WebOb的文档 ,或wsgify源代码。
关于装饰器的理解,不如自己撸一个简单的装饰器试试!
# 创建一个类wrapper,作为装饰器
class wrapper:
def __init__(self, func=None):
self.func = func
def __call__(self, x, *args):
return self.func(x) + 1
@wrapper
def simple_f(x):
return 2 * x
# -- main --
x = 3
y = simple_f(x)
print(y)
这段代码的输出是:
'''
7
'''