WSGI应用常见的几种写法
2013-04-03 11:15
323 查看
Python WSGI标准PEP-0333中说到一个WSGI是一个可调用callable的对象,这包含了一个函数,一个方法,一个类,或者拥有call方法的实例。下面我就对这句话做一个总结,举几个例子。这里的WSGI应用的功能都是返回请求的环境信息environ。
采用简单的WSGI服务器参考实现,如下:
这是最简单的方法,先调用
相应的服务端:
类定义中实现call方法,WSGI应用是这个类的一个实例。
服务端:
用类作为WSGI应用不太一样,调用这个类时会产生一个类的实例,这个实例随后会需要iter迭代返回值。
服务端:
这里注意,和上面的比较可以看出,如果需要把类的实例作为WSGI应用,则类中需要实现call方法,并且作为WSGI应用的应该是这个类的实例。
用一个方法来作为WSGI应用,那么这个方法不可能是实例方法(上面已经讲过),一种方式肯定就是类中的静态方法了,类中的静态方法,就当做一个全局函数一样理解吧。
服务端:
那么,类方法,可以用么,当然可以,
服务端:
上面中说到了WSGI应用的几种基本形式,这一节就来说一些高级的用法,所谓高级,我理解的也就是使用装饰器
WebOb就是将请求和相应封装成Request和Response类,就可以使用一个类方法简化真个操作,如下,直接将一个字符串作为resp_body传给给Response对象,而不用考虑WSGI中的可迭代对象,这里要注意,Response对象
服务端:
用装饰器@以后,重要的思想就是把WSGI应用关于返回流程的处理(包括header,状态等)和返回Body的处理分开,这样的话实际上一个应用只关注于产生返回的Body就可,而其他的处理流程则交给装饰器controller来完成,这个controller,不要理解成控制神马的,只是一个名字,其原意是作为WSGI中
服务端:
上面两种方式可能看起来没多大用,但是二者结合到一起,那就不一般了,这样子的话我们用装饰器controller来处理environ,并封装Request和Response,最后让应用函数来处理返回信息,只给出一个字符串Body就可以了。这会大大简化WSGI应用的开发流程。
服务端:
以上是用装饰器来装饰一个函数,还有一种用法,用装饰器来装饰一个类。
上面关于类的装饰器可以仔细琢磨一下哈,相应的服务端:
两篇文章我一共说明了9种WSGI应用的写法,当然WSGI只是一个协议,相应的实现还是很灵活的,以后再实践中再分享一些新的用法。整个代码我使用Gist存放,连接在此:https://gist.github.com/4378216
原创文章,转载请注明: 转载自Wang
Chang's Blog
本文链接地址: http://blog.wachang.net/2013/03/wsgi-application-style-adv/
1 服务端
采用简单的WSGI服务器参考实现,如下:if __name__ == '__main__': from wsgiref.simple_server import make_server server = make_server('192.168.1.11', 7070, wsgi_application) server.serve_forever()
2 函数方法
这是最简单的方法,先调用start_response()处理返回头信息,函数再返回可迭代对象,比如列表或者字符串。
def app1(environ,start_response): start_response("200 OK",[("Content-type","text/plain")]) content = [] for k,v in environ.iteritems(): content.append('%s:%s \n' % (k,v)) return content#返回的列表或者字符串
相应的服务端:
server = make_server('192.168.1.11', 7070, app1)
3 带有call方法的实例
类定义中实现call方法,WSGI应用是这个类的一个实例。class app2(object): def __init__(self): pass def __call__(self,environ,start_response): start_response("200 OK",[("Content-type","text/plain")]) content = [] for k,v in environ.iteritems(): content.append('%s:%s \n' % (k,v)) return content#返回的列表或者字符串 application = app2()
服务端:
server = make_server('192.168.1.11', 7070, application)
4 类class
用类作为WSGI应用不太一样,调用这个类时会产生一个类的实例,这个实例随后会需要iter迭代返回值。class app3(object): def __init__(self, environ, start_response): self.environ = environ self.start = start_response def __iter__(self): status = '200 OK' response_headers = [('Content-type', 'text/plain')] self.start(status, response_headers) content = '' for k,v in self.environ.iteritems(): content += '%s:%s \n' % (k,v) yield content#返回的是字符串
服务端:
server = make_server('192.168.1.11', 7070, app3)
这里注意,和上面的比较可以看出,如果需要把类的实例作为WSGI应用,则类中需要实现call方法,并且作为WSGI应用的应该是这个类的实例。
5 方法method
用一个方法来作为WSGI应用,那么这个方法不可能是实例方法(上面已经讲过),一种方式肯定就是类中的静态方法了,类中的静态方法,就当做一个全局函数一样理解吧。class app4(object): def __init__(self): pass @staticmethod def wsgi(environ,start_response): start_response("200 OK",[("Content-type","text/plain")]) content = [] for k,v in environ.iteritems(): content.append('%s:%s \n' % (k,v)) return content#返回的是列表或者字符串
服务端:
server = make_server('192.168.1.11', 7070, app4.wsgi)
那么,类方法,可以用么,当然可以,
classmethod和
staticmethod在使用上可以看做只是参数有个区别而已,如下:
class app5(object): def __init__(self): print 'This is app5' pass @classmethod def wsgi(cls,environ,start_response): start_response("200 OK",[("Content-type","text/plain")]) content = [] for k,v in environ.iteritems(): content.append('%s:%s \n' % (k,v)) return content #返回列表或者字符串
服务端:
server = make_server('192.168.1.11', 7070, app5.wsgi)
上面中说到了WSGI应用的几种基本形式,这一节就来说一些高级的用法,所谓高级,我理解的也就是使用装饰器
@,WebOb,以及中间件的形式,当然,还有一些更有意思的用法,比如Paste.Deploy这种载入WSGI应用的形式,我以后会做总结。还是和前篇WSGI应用常见的几种写法-基本形式一样,本文实现的WSGI应用都是一个回显请求环境信息的程序。
1 WebOb
WebOb就是将请求和相应封装成Request和Response类,就可以使用一个类方法简化真个操作,如下,直接将一个字符串作为resp_body传给给Response对象,而不用考虑WSGI中的可迭代对象,这里要注意,Response对象是一个WSGI应用,所以在最后的时候我们使用
resp(environ,start_response)就返回了,我们不关心返回的细节问题了,而在标准WSGI中,这一步才只是WSGI应用的入口函数。
def app6(environ, start_response): req = Request(environ) resp_body = '' for k,v in req.environ.iteritems(): resp_body += '%s:%s\n' % (k,v) resp = Response(body=resp_body) return resp(environ, start_response)
服务端:
server = make_server('192.168.1.11', 7070, app6)
2 用装饰器@,Controller
用装饰器@以后,重要的思想就是把WSGI应用关于返回流程的处理(包括header,状态等)和返回Body的处理分开,这样的话实际上一个应用只关注于产生返回的Body就可,而其他的处理流程则交给装饰器controller来完成,这个controller,不要理解成控制神马的,只是一个名字,其原意是作为WSGI中一个资源的控制,不用太操心就当做一个名字就好。
def controller1(func): def application(environ,start_response): #do something else resp_body = func(environ) start_response("200 OK",[("Content-type","text/plain")]) return resp_body return application @controller1 def app7(environ): content = [] for k,v in environ.iteritems(): content.append('%s:%s \n' % (k,v)) return content
服务端:
server = make_server('192.168.1.11', 7070, app7)
3 结合WebOb和装饰器
上面两种方式可能看起来没多大用,但是二者结合到一起,那就不一般了,这样子的话我们用装饰器controller来处理environ,并封装Request和Response,最后让应用函数来处理返回信息,只给出一个字符串Body就可以了。这会大大简化WSGI应用的开发流程。def controller2(func): def replacement(environ, start_response): req = Request(environ) try: resp_body = func(req) except exc.HTTPException, e: resp_body = e resp = Response(body=resp_body)#body must be a string resp.status = '200 very OK' return resp(environ, start_response) return replacement @controller2 def app8(req): ret = '' for k,v in req.environ.iteritems(): ret = ret + '%s:%s \n' % (k,v) return ret
服务端:
server = make_server('192.168.1.11', 7070, app8)
以上是用装饰器来装饰一个函数,还有一种用法,用装饰器来装饰一个类。
def controller3(cls): def replacement(environ, start_response): req = Request(environ) instance = cls(req, **req.urlvars) method = req.method if method == 'GET': func = getattr(instance, method.lower()) resp_body = func() if isinstance(resp_body, basestring): resp = Response(body=resp_body) return resp(environ,start_response) return replacement class App9(object): def __init__(self,req,**args): self.req = req def get(self): body = '' for k,v in self.req.environ.iteritems(): body += '%s"%s \n' % (k,v) return body app9 = controller3(App9)
上面关于类的装饰器可以仔细琢磨一下哈,相应的服务端:
server = make_server('192.168.1.11', 7070, app9)
4 总结
两篇文章我一共说明了9种WSGI应用的写法,当然WSGI只是一个协议,相应的实现还是很灵活的,以后再实践中再分享一些新的用法。整个代码我使用Gist存放,连接在此:https://gist.github.com/4378216原创文章,转载请注明: 转载自Wang
Chang's Blog
本文链接地址: http://blog.wachang.net/2013/03/wsgi-application-style-adv/
相关文章推荐
- Android项目-几种常见的应用架构
- JavaScript函数的常见几种写法
- Android项目-几种常见的应用架构
- 几种常见复合sql查询语句的linq写法[继续补充中]
- Android项目-几种常见的应用Tab架构
- SQL Server 存储过程中处理多个查询条件的几种常见写法分析,我们该用那种写法
- Android应用的几种常见开发框架
- 常见多媒体播放器的几种写法
- 归纳下js面向对象的几种常见写法总结
- Android项目-几种常见的应用架构
- javascript对象和函数的几种常见写法
- 几种常见窗函数及其matlab应用
- 归纳下js面向对象的几种常见写法
- 几种常见的Android自动化测试框架及其应用
- 几种常见树--基本概念及应用领域
- XML几种常见应用:
- Android项目-几种常见的应用架构
- 什么是内存溢出与内存泄露,几种常见导致内存泄露的写法
- js面向对象的几种常见写法
- Android - VGA,ADB,DDMS,安卓开发环境目录结构,安卓目录结构,常见布局,点击事件的几种写法,控件(Button/TextView/ImageView/EditText)