WSGI框架及Paste+Pastedeploy+route+webob开发
一。前言
WSGI服务器
一个Web服务器网关接口 (WSGI)服务器实现了WSGI接口的Web服务器端运行的Python的Web应用程序。
为什么需要WSGI?
传统的Web服务器不理解或有任何方式来运行Python应用程序。在20世纪90年代后期,名为Grisha Trubetskoy的开发人员 提出了一个名为mod_python的Apache模块 来执行任意的Python代码。在20世纪90年代后期和21世纪初,Apache配置的mod_python运行了大多数Python Web应用程序。
但是,mod_python不是标准规范。这只是一个允许Python代码在服务器上运行的实现。由于mod_python的开发陷入僵局,安全漏洞被发现,社区认识到,需要一致的方式来执行Web应用程序的Python代码。
因此,Python社区提出了WSGI作为模块和容器可以实现的标准接口。WSGI现在是运行Python Web应用程序的被接受的方法。
WSGI官方规范
WSGI标准v1.0在PEP 0333中指定 。截至2010年9月,WSGI v1.0被PEP 3333取代 ,它定义了v1.0.1 WSGI标准。如果您使用Python 2.x,并且您符合PEP 0333,那么您也符合3333.较新版本仅仅是Python 3的更新,并且有关于如何处理unicode的说明。
在的wsgiref的Python 2.x中和 的wsgiref在Python 3.x的 是内置到Python的标准库WSGI规范的参考实现,因此它可以被用来建造WSGI服务器和应用程序
PEP 0333 – Python Web Server Gateway Interface 是一种 web server or gateway 和 python web application or framework 之间简单通用的接口,符合这种接口的 application 可运行在所有符合该接口的 server 上。通俗的讲,WSGI 规范了一种简单的接口,解耦了 server 和 application,使得双边的开发者更加专注自身特性的开发。
- Web server/gateway: 即 HTTP Server,处理 HTTP 协议,接受用户 HTTP 请求和提供并发,调用 web application 处理业务逻辑。通常采用 C/C++ 编写,代表:apache, nginx 和 IIS。
- Python Web application/framework: 专注业务逻辑的 python 应用或者框架
Python Web application/framework
Application/framework 端必须定义一个 callable object,callable object 可以是以下三者之一:
- function, method
- class
- instance with a __call__ method
Callable object 必须满足以下两个条件:
- 接受两个参数:字典(environ),回调函数(start_response,返回 HTTP status,headers 给 web server)
- 返回一个可迭代的值
示例:
- def application(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/plain')])
- return ['HELLO WORLD!']
- class ApplicationClass(object):
- def __init__(self, environ, start_response):
- self.environ = environ
- self.start_response = start_response
- def __iter__(self):
- self.start_response('200 OK', [('Content-type', 'text/plain')])
- yield "Hello world!n"
environ
和start_response
由 http server 提供并实现environ
变量是包含了环境信息的字典Application
内部在返回前调用start_response
start_response
也是一个 callable,接受两个必须的参数,status
(HTTP状态)和response_headers
(响应消息的头)- 可调用对象要返回一个值,这个值是可迭代的
服务器接口端
服务器端主要专注 HTTP 层面的业务,重点是接收 HTTP 请求和提供并发。
每当收到 HTTP 请求,服务器接口端必须调用 callable object:
- 接收 HTTP 请求,但是不关心 HTTP url, HTTP method 等
- 为 environ 提供必要的参数,实现一个回调函数 start_response,并传给 callable object
- 调用 callable object
Middleware,中间件
Middleware 处于 服务层和 应用接口层 之间,每个 middleware 实现不同的功能,我们通常根据需求选择相应的 middleware 并组合起来,实现所需的功能。其作用有以下几点:
- 根据 url 把用户请求调度到不同的 application 中。
- 负载均衡,转发用户请求
- 预处理 XSL 等相关数据
- 限制请求速率,设置白名单
- class IPBlacklistMiddleware(object):
- def __init__(self, app):
- self.app = app
- def __call__(self, environ, start_response):
- ip_addr = environ.get('HTTP_HOST').split(':')[0]
- if ip_addr not in ('127.0.0.1'):
- return forbidden(start_response)
- return self.app(environ, start_response)
- def forbidden(start_response):
- start_response('403 Forbidden', [('Content-Type', 'text/plain')])
- return ['Forbidden']
- def application(environ, start_response):
- start_response('200 OK', [('Content-Type', 'text/plain')])
- return ['Hello World!']
- if __name__ == '__main__':
- from wsgiref.simple_server import make_server
- application = IPBlacklistMiddleware(application)
- server = make_server('0.0.0.0', 8080, application)
- server.serve_forever()
大致了解WSGI框架后我们来看下Paste+Pastedeploy+route+webob开发,openstack开发使用的就是此开发框架,主要使用到的一些模块是:
- eventlet: python 的高并发网络库
- paste.deploy: 用于发现和配置 WSGI application 和 server 的库
- routes: 处理 http url mapping 的库
- webob: 处理HTTP请求并提供了一个对象来方便的处理返回response消息
Eventlet
Eventlet 是一个基于协程的 Python 高并发网络库,额以下特点:
- 使用 epoll、kqueue 或 libevent 等 I/O 复用机制,对于非阻塞 I/O 具有良好的性能
- 基于协程(Coroutines),和进程、线程相比,其切换开销更小,具有更高的性能
- 简单易用,特别是支持采用同步的方式编写异步的代码
paste.deploy
Paste Deployment是用于查找和配置WSGI应用程序和服务器的系统。对于WSGI应用程序消费者,它提供了从配置文件或Python Egg加载WSGI应用程序的单一简单函数(loadapp)。对于WSGI应用程序提供商,它只需要一个简单的入口点到您的应用程序,以便应用程序用户不需要暴露于应用程序的实现细节。
Paste.deploy 通常要求 application 实现一个 factory 的类方法,如下:
- class TestApplication(object):
- def __init__(self):
- pass
- @webob.dec.wsgify
- def __call__(self, req):
- return self.router
- @classmethod
- def factory(cls, global_conf, **local_conf):
- return cls()
- if '__main__' == __name__:
- application = loadapp('config:%s/config.ini' % (CONF))
- server = eventlet.spawn(wsgi.server,
- eventlet.listen(('0.0.0.0', 8080)), application)
- server.wait()
Paste.deploy 的.ini配置文件配置 讲解
配置文件说明,一个配置文件有不同的分段,但pastedeploy 关心的是前缀,比如app:main or filter:errors,:分隔部分之后是是这个分段的name,前一部分是这个分段的type类型,前段给的类型,后段名字将被忽略。
一个简单的INI配置文件格式是 name = value.可以通过缩进后续行来扩展配置,#是对前面配置的评论标注。
通常,您有一个或两个部分,称为“main”:一个应用程序部分(app:main)和一个服务器部分(server:main)。(复合:…表示向多个应用程序发送的内容(如以下示例)。
- [composite:main]
- use = egg:Paste#urlmap
- / = home
- /blog = blog
- /wiki = wiki
- /cms = config:cms.ini
- [app:home]
- use = egg:Paste#static
- document_root = %(here)s/htdocs
- [filter-app:blog]
- use = egg:Authentication#auth
- next = blogapp
- roles = admin
- htpasswd = /home/me/users.htpasswd
- [app:blogapp]
- use = egg:BlogApp
- database = sqlite:/home/me/blog.db
- [app:wiki]
- use = call:mywiki.main:application
- database = sqlite:/home/me/wiki.db
urlmap 相当于做了多路由的分发,请求http://xxxx/ 时会请求分段名称为home的app, 走到相对的处理函数或者controller,其他类同
第一分段解释:
- [composite:main]
- use = egg:Paste#urlmap
- / = home
- /blog = blog
- /cms = config:cms.ini
composite 分段将请求分发给其他applications程序,use = egg:Paste#urlmap 意思是这个composite程序将使用paste名称为urlmap的包, urlmap是一个特别常见的复合应用程序,它使用路径前缀将请求映射到另一个应用程序。其他的如/ /blog 是应用程序,最后一个/cms,表明指的是另一个ini配置文件。
- [app:home]
- use = egg:Paste#static
- document_root = %(here)s/htdocs
egg:Paste#static 静态文件配置,使用paste包static只提供静态文件,需要指定document_root目录
使用方法
- from paste.deploy import loadapp
- wsgi_app = loadapp('config:/path/to/config.ini')
section的type可以有:app、composite、filter、pipeline、filter-app等。学习具体更多配置详参官网
Route
Routes 是基于 ruby on rails 的 routes system 开发的 python 库,它根据 http url 把请求映射到具体的方法,routes 简单易用,可方便的构建 Restful 风格的 url。
示例:
- import eventlet
- from eventlet import wsgi
- from paste.deploy import loadapp
- import routes
- import routes.middleware as middleware
- import webob.dec
- import webob.exc
- from manager.settings import CONF
- class TestController(object):
- def index(self, req):
- return 'GET'
- def create(self, req):
- return 'POST'
- def delete(self, req):
- return 'DELETE'
- def update(self, req):
- return 'PUT'
- class Resource(object):
- def __init__(self, controller):
- self.controller = controller()
- @webob.dec.wsgify
- def __call__(self, req):
- match = req.environ['wsgiorg.routing_args'][1]
- action = match['action']
- if hasattr(self.controller, action):
- method = getattr(self.controller, action)
- return method(req)
- return webob.exc.HTTPNotFound()
- class TestApplication(object):
- def __init__(self):
- self.mapper = routes.Mapper()
- self.mapper.resource('test', 'tests', controller=Resource(TestController))
- self.router = middleware.RoutesMiddleware(self.dispatch, self.mapper)
- @webob.dec.wsgify
- def __call__(self, req):
- return self.router
- @classmethod
- def factory(cls, global_conf, **local_conf):
- return cls()
- @staticmethod
- @webob.dec.wsgify
- def dispatch(req):
- match = req.environ['wsgiorg.routing_args'][1]
- return match['controller'] if match else webob.exc.HTTPNotFound()
- if '__main__' == __name__:
- application = loadapp('config:%s/config.ini' % (CONF))
- server = eventlet.spawn(wsgi.server,
- eventlet.listen(('0.0.0.0', 8080)), application)
- server.wait()
WSGI框架及Paste+Pastedeploy+route+webob开发的更多相关文章
- Openstack Restful API 开发框架 Paste + PasteDeploy + Routes + WebOb
目录 目录 Paste PasteDeploy Routes WebOb 简介 WSGI入口 Paste和PasteDeploy 配置文件 pasteini 中间件的实现 Routes WebOb 参 ...
- 使用MVVM框架(avalonJS)进行快速开发
背景 在运营活动开发中,因为工作的重复性很大,同时往往开发时间短,某些情况下也会非常紧急,导致了活动开发时间被大大压缩,同时有些活动逻辑复杂,数据或者状态变更都需要手动渲染,容易出错,正是因为这些问题 ...
- Scala 的 Web 框架 Lift 开始 3.0 版本开发
Scala 的 Web 框架 Lift 开始 3.0 版本开发 http://demo.liftweb.net/ http://liftweb.net/download Lift 框架在不断的成长和改 ...
- django框架实现restful风格的API开发
RESTful风格的要求:https://www.cnblogs.com/chichung/p/9933116.html 利用django原生的框架直接做RESTful的API开发是怎样的呢?感受一下 ...
- python-django框架-电商项目-订单模块开发_20191125
python-django框架-电商项目-订单模块开发 提交订单页面: 在购物车中点击提交订单,就应该到达提交订单页面了, 显示: 1,收获地址, 2,支付方式 3,用户购买的商品信息,数量,小计, ...
- python-django框架-电商项目-购物车模块开发_20191125
python-django框架-电商项目-购物车模块开发 商品详情页js代码: 在商品详情页,有加入购物车按钮, 点击加减号可以增加减少,手动输入也可以, 点击加入购物车,就要加过去, 先实现加减的操 ...
- nodejs 中koa框架下的微信公众号开发初始篇
最近在搞微信公众号开发,后端采用的是nodejs下的koa框架,初识后端的菜鸟,自己搞难度太大了,网上找了很多文章,采用的中间件大都是express框架下的,不过好在爬了许多坑之后总算看见点曙光了,遂 ...
- (转)python WSGI框架详解
原文:https://www.cnblogs.com/shijingjing07/p/6407723.html?utm_source=itdadao&utm_medium=referral h ...
- WSGI学习系列Paste
Paste has been under development for a while, and has lots of code in it. The code is largely decoup ...
随机推荐
- Mybatis第五篇【Mybatis与Spring整合】
Mybatis与Spring整合 既然我们已经学了Mybatis的基本开发了,接下来就是Mybatis与Spring的整合了! 以下使用的是Oracle数据库来进行测试 导入jar包 aopallia ...
- 关于极光推送Jpush的demo
关于极光推送Jpush 推送是手机app必不可少的一样功能,这次由于公司项目需要研究了一下.由于推送一般写于服务端,所以对于不会Android的javaweb程序员要写出一个完整的demo是一件很头痛 ...
- MongoDB 复制篇
mongoDB 复制篇 复制集简介 Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写 ...
- 过度拟合(overfilting)
过拟合概念:是指分类器能够百分之百的正确分类样本数据(训练集中的样本数据),对训练集以外的数据却不能够正确分类. 原因:1:模型(算法)太过复杂,比如神经网络,算法太过精细复杂,规则太过严格,以至于任 ...
- ACM-ICPC北京赛区(2017)网络赛_Minimum
题目9 : Minimum 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 You are given a list of integers a0, a1, -, a2^k ...
- Linux JDK配置
第一步:下载jdk-7-linux-i586.tar.gz wget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586 ...
- CentOS 7搭建LAMP环境(一)
CentOS是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定释出的源代码所编译而成.由于出自同样的源代码,因此有些要求高度稳定性的服务器以CentO ...
- [bzoj1066] [SCOI2007] 蜥蜴 - 网络流
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个 ...
- js-注释代码习惯
功能块代码 /** * xxxx */ 定义的函数或方法 /* xxxx */ 调用了某个函数或方法 // <--xxx
- 【转】python数据格式化之pprint
pprint – 美观打印 作用:美观打印数据结构 pprint 包含一个“美观打印机”,用于生成数据结构的一个美观视图.格式化工具会生成数据结构的一些表示,不仅可以由解释器正确地解析,而且便于人类阅 ...