WebOb和通用标准实现WSGI框架的比较
来源:互联网 发布:python exit code 9 编辑:程序博客网 时间:2024/05/16 07:07
http://tumblr.wachang.net/post/38298360375/webob-wsgi-framework-diff
作者都是Ian Bicking,两个框架分别是遵循WSGI标准的WSGI框架
(以下以1方法表示)以及使用Webob来实现WSGI框架
(以下一2方法表示),两篇文章的地址分别是:http://pythonpaste.org/do-it-yourself-framework.html,http://docs.webob.org/en/latest/do-it-yourself.html,这里对两个文章做一个总结比较。
基本概念
controller:就是WSGI应用,2方法中格式为module_name:function_name
routes:
webob是一个创建请求和回复对象的库,webob对于请求和回应的封装能力,提供了一种简单测试WSGI应用的方法,如下:
>>> from webob import Request>>> req = Request.blank('http://localhost/test')>>> resp = req.get_response(application)>>> print resp200 OKContent-Type: text/htmlHello World!
请求部分
在普通的WSGI中,请求的信息是environ,这是一个类似CGI的字典形式。而使用webob,需要创建一个request对象,这是对environ的一个包装。如下:
from webob import Requestdef app(environ, start_response): print 'This is environ info',environ['HTTP_HOST'] start_response('200 OK', [('content-type', 'text/html')]) req = Request(environ) print 'This is Request info',req.environ['HTTP_HOST'] return ['Hello world!']root@Node1:~/python# python wsgi.py serving on http://192.168.1.11:8080This is environ info 192.168.1.11:8080This is Request info 192.168.1.11:8080
关于返回
通常是函数中先调用start_response,然后函数返回可迭代对象,webob中直接构造Response对象,说白了,Response对象就是一个WSGI应用,如下:
from webob import Requestfrom webob import Responsedef app(environ,start_response): resp = Response(body='Hello World!') resp.content_type='text/html' print resp return resp(environ,start_response)httpserver.serve(app, host='192.168.1.11', port='8080')root@Node1:~/python# python wsgi.py serving on http://192.168.1.11:8080200 OKContent-Length: 12Content-Type: text/html; charset=UTF-8
关于WSGI服务器
官方有两个参考,都可以:
from paste import httpserver httpserver.serve(app, host='127.0.0.1', port=8080)from wsgiref.simple_server import make_server server = make_server('127.0.0.1', 8080, app) server.serve_forever()
Webob实现的WSGI框架
所谓的routes,router就是根据HTTP请求的PATH的层次调度到不同的WSGI应用上面去。2中使用了Router这个类来实现,如下:
app = Router() app.add_route(‘/’, controller=’controllers:index’) app.add_route(‘/post’, controller=’controllers:post’)
有了router以后,我们就要看看如何载入这个controller了,根据controller的格式,我们需要载入一个模块,然后执行函数,所以写了一个此功能的函数:
import sysdef load_controller(string): module_name, func_name = string.split(':', 1) #分割出module和func的名字 __import__(module_name) #buildin函数,载入模块 module = sys.modules[module_name] #import的返回不好处理,所以这里返回Model名字 func = getattr(module, func_name) return func #返回函数对象
Router有add_route方法可以加入路由香,并且Router实例有call方法,着同样,ROuter实例就可以当做一个WSGI应用来使用了。所以当一个请求到来的时候,它会根据PATH_INFO(req.path_info)作为匹配,并传递到相应的controller(WSGI应用),Router的代码如下:
from webob import Requestfrom webob import excclass Router(object): def __init__(self): self.routes = [] #里面是元组,每个元组包含了匹配规则,相应的应用 def add_route(self, template, controller, **vars): if isinstance(controller, basestring): controller = load_controller(controller) self.routes.append((re.compile(template_to_regex(template)), controller, vars)) def __call__(self, environ, start_response): req = Request(environ) for regex, controller, vars in self.routes: match = regex.match(req.path_info) if match: req.urlvars = match.groupdict() req.urlvars.update(vars) return controller(environ, start_response) return exc.HTTPNotFound()(environ, start_response)
我们详细看看这个函数:
self.routes = [],是一个匹配表,表中内容为(regex, controller, vars)
add_route会判断controller应用是字符串或者是对象,都可以处理,如果是对象,需要实现call方法。
__call__
方法使你可以像函数一样调用一个对象。对于请求,产生了一个request object对象,controller可以选择以request对象作为参数(在最后返回response(environ,start_response)),或者直接处理(environ,start_response)参数。
req.urlvars变量实际上是environ[‘wsgiorg.routing_args’]的一个映射,environ[‘wsgiorg.routing_args’]是经过match以后,WSGI应用对请求信息的修改,加入了这个wsgiorg.routing_args,值就为匹配的一些参数。
webob.exc.HTTPNotFound()是一个 WSGI application 用于返回404回应(注意还是要以environ和start_response参数调用).也可以加入自定义信息webob.exc.HTTPNotFound(‘No route matched’)(environ,start_response)
基本流程清楚以后,就是来看看controller端了,controller就是一个WSGI应用,但是为了简单的写应用,一般框架都会提供一个装饰器(把一个函数装饰warp成另外一个函数),利用这个装饰器,可以简化controller的开发,如下一个装饰器:
from webob import Request, Responsefrom webob import excdef controller(func): #func是自己写的应用 def replacement(environ, start_response): req = Request(environ) #首先封装environ环境 try: resp = func(req, **req.urlvars) #将请求和附加参数传给应用处理。返回resp是一个字符串或者一个Response对象。 except exc.HTTPException, e: resp = e if isinstance(resp, basestring):#如果应用返回一个字符串,那么就封装为Response对象 resp = Response(body=resp) return resp(environ, start_response)#Response对象是一个WSGI应用,如此调用的话就成功返回。返回的是自己,webob特色! return replacement#函数定义中调用另外一个函数,用这种方式。
经过如上装饰以后,自己写的WSGI应用就只需要两个参数controller_func(req, **urlvars)了,确实简化了,不用考虑一直保持environ,start_response的传递了。然后这个装饰器就可以如下使用:
@controllerdef index(req): return 'This is the index'
再来一个复杂一点的:
@controllerdef hello(req): if req.method == 'POST': return 'Hello %s!' % req.params['name'] elif req.method == 'GET': return '''<form method="POST"> You're name: <input type="text" name="name"> <input type="submit"> </form>'''hello_world = Router()hello_world.add_route('/', controller=hello)
上面一个WSGI应用实际上是一个函数,前面说到,一个WSGI应用也可以是一个类。这样的话,在写controller装饰器的时候,就要注意一点用法:
def rest_controller(cls): def replacement(environ, start_response): req = Request(environ) try: instance = cls(req, **req.urlvars) method = getattr(instance, action) resp = method() resp = Response(body=resp) return resp(environ, start_response) return replacement
action是req中的方法,method是类中的的方法,method()就是一个相应的执行。
class Hello(object): def __init__(self, req): self.request = req def get(self): return '''<form method="POST"> You're name: <input type="text" name="name"> <input type="submit"> </form>''' def post(self): return 'Hello %s!' % self.request.params['name']hello = rest_controller(Hello)
- WebOb和通用标准实现WSGI框架的比较
- Webob WSGI 装饰器
- WSGI Webob Routes 实例
- WSGI Webob Routes 实例
- Webob WSGI 装饰器
- WSGI、webob、routes实例
- Python的WSGI框架
- 【OpenStack】WSGI and Webob+Paste示例
- 用Webmagic和MongoDB实现的通用化爬虫框架
- 化整为零的次世代网页开发标准: WSGI
- 化整为零的次世代网页开发标准: WSGI
- 化整为零的次世代网页开发标准: WSGI
- wsgi+webob+routes学习笔记-初学篇(上)
- wsgi+webob+routes学习笔记-初学篇(中)
- wsgi+webob+routes学习笔记-初学篇(下)
- wsgi+webob+routes学习笔记-初学篇(end)
- openstack基础之python WSGI,paste,Routes,webob
- openstack基础之python WSGI,paste,Routes,webob
- Win7下安装JDK + Tomcat7.0
- Android游戏开发cocos2d-x调用Java层代码
- 美国USA152间谍卫星参数
- Apache2.2和Tomcat6整合
- sql getdate() 时间格式设置
- WebOb和通用标准实现WSGI框架的比较
- C++使用jsoncpp库问题
- Python中处理HTTP协议的库:urllib2
- Oracle 字符集的查看和修改
- C++处理UTF8编码的字符串
- 十五、从互联网获取图片且保存到指定目录
- 静态库和动态库的区别
- 快速排序
- jqModal点击弹窗外背景不关闭弹窗