如何使用Paste.Deploy
转自:http://bingotree.cn/?p=100
1.Paste Deploy的一个组件,但是并不依赖于Paste的其它组件。其可以看成是一个独立的包。其主要用于通过一个配置文件完成WSGI应用和服务器的构建。对于一个不怎么了解Python的人来说,只要知道了这个配置文件如何编写,那么也能写出一个符合WSGI标准的应用。这样说可能还是有点抽象,下面看了例子就清楚了。
2.安装PasteDeploy
1
2
3
|
[root@OS_DEV ~]# pip install PasteDeploy Requirement already satisfied (use --upgrade to upgrade): PasteDeploy in /usr/lib/python2.6/site-packages Cleaning up... |
3.配置文件
这个是官网的一个配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[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 |
首先,配置文件分为多个section,每个section的名字的格式是TYPE:NAME,每个section中参数的格式一般是KEY = VALUE。我们分别来看看各种TYPE:
3.1 TYPE = composite
1
2
3
4
5
6
|
[composite:main] use = egg:Paste#urlmap / = home /blog = blog /wiki = wiki /cms = config:cms.ini |
composite这个类型的section会的把具体的URL请求分配到VALUE对应的section中的APP上去。use表明具体的分配方
法,换句话说这里的KEY =
VALUE是egg:Paste#urlmap这个Python模块的参数,个人猜测egg:Paste#urlmap的实现应该类似于:
1
2
3
|
if (URL = = "/" ) call(home_app) if (URL = = "/blog" ) call(wiki) if (URL = = "/cms" ) call(config:cms.ini) |
3.2 TYPE = app
1
2
3
|
[app:home] use = egg:Paste#static document_root = %(here)s/htdocs |
一个app就是一个具体的WSGI的应用。具体调用那个python module中的app则由use来指定。use有很多类型,比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
[app:myapp] use = config:another_config_file.ini#app_name # or any URI: [app:myotherapp] use = egg:MyApp # or a callable from a module: [app:mythirdapp] use = call:my.project:myapplication # or even another section: [app:mylastapp] use = myotherapp |
其实也不难,大概看看就知道每种的含义了。config:another_config_file.ini#app_name表示从另外一个
config.ini文件中找app。egg:MyApp是从python蛋中找。call:my.project:myapplication是直接调
用某个模块中的myapplication。use = myotherapp则是在其它section找app。
另外还有一种调用方法:
1
2
|
[app:myapp] paste.app_factory = myapp.modulename:app_factory |
这里直接指定了使用myapp.modulename中的app_factory作为我们的app。paste.app_factory表明表明了我们的app_factory所使用的格式,app_factory的相关格式、参数、返回值我们下面会讲到。
另外在section中的其它KEY = VALUE对则是会的被当成参数传到我们的app中。
3.3 TYPE = filter-app
1
2
3
4
5
6
7
8
9
|
[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 |
filter-app就是一个过滤,也就是说一个请求过来后,会的先走filter-app中的use指定的app,如果那个app过滤了这个
request,那么这个request就不会发送到next指定的app中去进行下一步处理了。如果没有过滤,则会发送给next指定的app。这个
filter-app虽然有过滤的名字,但其实也不一定要做过滤这档子事情,可以用来记录些日志啥的,比如每次来个请求就log些东西,然后再转给后面的
app去处理。fiter-app必须要有next,这个和filter不一样
3.4 TYPE = filter
1
2
3
4
5
6
7
|
[app:main] use = egg:MyEgg filter-with = printdebug [filter:printdebug] use = egg:Paste#printdebug # and you could have another filter-with here, and so on... |
和filter-app差不多,但是没有next
3.5 TYPE = pipeline
1
2
3
4
5
|
[pipeline:main] pipeline = filter1 egg:FilterEgg#filter2 filter3 app [filter:filter1] ... |
pipeline就是简化了filter-app,不然你想,如果我有十个filter,那不是要写十个filter-app,然后用next连起
来?所以通过pipeline,我就可以把这些filter都连起来写在一行,很方便。但要注意的是这些filter需要有一个app作为结尾。
4.基本用法
如何使用呢?很简单。我们都说了,这个Paste Deploy就是为了从配置文件生成一个WSGI的APP,所以只要这样调用就行了:
1
2
|
from paste.deploy import loadapp wsgi_app = loadapp( 'config:/path/to/config.ini' ) |
5.全局section
这个很好理解,看个例子:
1
2
3
4
5
6
|
[DEFAULT] admin_email = webmaster@example.com [app:main] use = ... set admin_email = bob@example.com |
main这个app里会有一个参数admin_email传递进去,默认就是DEFAULT中的那个,当然可以通过set来覆盖。
6.具体的factory格式
PasteDeploy自身有很多的factory,这些factory对普通的WSGI标准做了个封装,让用的时候好用一些。我们来看看对应的格式:
6.1 paste.app_factory
1
2
|
def app_factory(global_config, * * local_conf): return wsgi_app |
这个比较简单,写的时候就是只要写一个我们需要的WSGI_APP就行了。
6.2 paste.composite_factory
1
2
|
def composite_factory(loader, global_config, * * local_conf): return wsgi_app |
这个其实就是比上面多了个loader方法,loader有get_app之类的方法。
6.3 paste.filter_factory
类似于paste.app_factory。和app_factory的区别在于paste.filter_factory返回的是一个filter。filter究竟是个啥?其实很简单,无非就是个if-else,比如:
1
2
|
if ("一切ok,没啥可以过滤的") return NEXT_WSGI_APP(XXX) else return "直接返回WSGI的标准返回报文,request请求链在这里就断了" |
这个是个形象的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
def auth_filter_factory(global_conf, req_usernames): # space-separated list of usernames: req_usernames = req_usernames.split() def filter (app): return AuthFilter(app, req_usernames) return filter class AuthFilter( object ): def __init__( self , app, req_usernames): self .app = app self .req_usernames = req_usernames def __call__( self , environ, start_response): if environ.get( 'REMOTE_USER' ) in self .req_usernames: return self .app(environ, start_response) start_response( '403 Forbidden' , [( 'Content-type' , 'text/html' )]) return [ 'You are forbidden to view this resource' ] |
换句话说,auth_filter_factory需要有一个filter的方法,假设有两个filter,那么Paste Deploy可能会生成这样的代码:
1
2
|
APP = filter01(WSGI_APP) = AuthFilter01 APP02 = filter02(AuthFilter01) = AuthFilter02 |
实际上调用的时候变成:
APP02(XXX,XXX),也就是AuthFilter02(XXX,XXX),而AuthFilter02会的先做过滤,如果过滤成功,那么直接由
他返回我们的HTTP报文,否则调用AuthFilter01,AuthFilter01也会做个过滤,如果过滤成功,则返回HTTP报文,否则调用最后
的WSGI_APP。
因此如果写在pipeline中,那么顺序就应该是:filter02 filter01 WSGI_APP
6.4 paste.filter_app_factory
这个的话就是把paste.filter_factory从function变成了class,原理是一样的。
6.5 paste.server_factory
生成一个WSGI标准的SERVER:
1
2
3
4
5
6
|
def server_factory(global_conf, host, port): port = int (port) def serve(app): s = Server(app, host = host, port = port) s.serve_forever() return serve |
这里的Server可以自由选择。
7.总结
说了这么多,来个总结吧。如果说我有一个pipeline是这个样子滴:
1
|
pipeline = filter01 filter02 app |
filter01对应的是TEST:filter01_factory
filter02对应的是TEST:filter02_factory
app对应的是TEST:app_factory
相关的代码可以是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
def filter01_factory(global_conf, XXX): def filter (app): return Filter01(app) return filter class Filter01( object ): def __init__( self , app,): self .app = app def __call__( self , environ, start_response): if "满足某个条件" : return self .app(environ, start_response) start_response( '403 Forbidden' , [( 'Content-type' , 'text/html' )]) return [ 'You are forbidden to view this resource' ] def filter02_factory(global_conf, XXX): def filter (app): return Filter02(app) return filter class Filter02( object ): def __init__( self , app,): self .app = app def __call__( self , environ, start_response): if "满足某个条件" : return self .app(environ, start_response) start_response( '403 Forbidden' , [( 'Content-type' , 'text/html' )]) return [ 'You are forbidden to view this resource' ] def app_factory(global_config, * * local_conf): return WSGI_APP #一个真正干活的的WSGI APP,符合WSGI的标准 |
那么根据上面的总结,paste会的生成如下的代码:
1
2
3
4
5
6
7
8
|
WSGI_APP = app_factory(XXX) FILTER01 = filter01_factory(XXX) FILTER02 = filter02_factory(XXX) CALLABLE_WSGI_APP = FILTER02(FILTER01(WSGI_APP)) #实际的请求格式会的是CALLABLE_WSGI_APP(XXX,XXX),这里的CALLABLE_WSGI_APP实际上变成了Filter02 s = Server(CALLABLE_WSGI_APP, host = host, port = port) s.serve_forever() |
如何使用Paste.Deploy的更多相关文章
- [原]Paste.deploy 与 WSGI, keystone 小记
Paste.deploy 与 WSGI, keystone 小记 名词解释: Paste.deploy 是一个WSGI工具包,用于更方便的管理WSGI应用, 可以通过配置文件,将WSGI应用加载起来. ...
- 探索 OpenStack 之(11):cinder-api Service 启动过程分析 以及 WSGI / Paste deploy / Router 等介绍
OpenStack 中的每一个提供 REST API Service 的组件,比如 cinder-api,nova-api 等,其实是一个 WSGI App,其主要功能是接受客户端发来的 HTTP R ...
- 自己使用python webob,paste.deploy,wsgi总结
paste.deploy就是一个可以配置wsgi_app的工具,可以让服务器运行时,按照配置文件执行一系列的程序.需要使用.ini配置文件. (1)这里补充一下当时没看到的配置文件 1.[app:ma ...
- Python Paste.deploy 笔记
首先python paste是一个WSGI工具包,在WSGI的基础上包装了几层,让应用管理和实现变得方便.说实话,Python Paste的文档做的真差劲!加之python代码可读性本来就不怎么滴,真 ...
- 详解Paste deploy
原创作品,转载注明本文出处:http://www.cnblogs.com/Security-Darren/p/4087587.html 谈到WSGI,就免不了要了解paste,其中paste depl ...
- keystone源码分析(一)——Paste Deploy的应用
本keystone源码分析系列基于Juno版Keystone,于2014年10月16日随Juno版OpenStack发布. Keystone作为OpenStack中的身份管理与授权模块,主要实现系统用 ...
- how to read openstack code : paste deploy
本篇分为以下几个部分 paste 是什么 怎样使用paste paste of neutron paste 是什么 WSGI 是python 中application 和 web server互通的标 ...
- paste deploy初探
这段时间刚着手开始研究Openstack Swift源码,为后续开发做准备. Swift依据python WSGI规范.WSGI(Web Server Gateway Interface)是Pytho ...
- WSGI框架及Paste+Pastedeploy+route+webob开发
一.前言 WSGI服务器 一个Web服务器网关接口 (WSGI)服务器实现了WSGI接口的Web服务器端运行的Python的Web应用程序. 为什么需要WSGI? 传统的Web服务器不理解或有任何方式 ...
随机推荐
- [Database]Operators
Arithmetic Operators +,-,×,÷ Comparison Operators =,<>,!=,>,<,>=,<= BETWEEN,IN,IS ...
- CloudTest 事务监控:千呼万唤始出来
SmartBear 数据表明,如果 Amazon 的加载时间延长 1 秒,那么一年就会减少 16 亿美元的营收.用户与网站互动的过程中,如果加载时间超过3秒,57% 的用户会流失.可见,网站的加载时间 ...
- pthread_create()之前的属性设置
一.pthread_create()之前的属性设置1.线程属性设置我们用pthread_create函数创建一个线程,在这个线程中,我们使用默认参数,即将该函数的第二个参数设为NULL.的确,对大多数 ...
- FZU-1924+判断环/DFS/BFS
dfs: /* dfs */ #include<stdio.h> #include<string.h> #include<stdlib.h> #include< ...
- Android 使用httpClient POST 模拟发送 multipart表单内容
使用的环境:apache-mime4j-0.6.jar,httpcore-4.3.2.jar,httpmime-4.3.3.jar try { HttpPost httpPost = new Http ...
- SQLite入门与分析(三)---内核概述(2)
写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...
- 手动添加 memcached.jar包
由于目前java memcached client没有官方的maven repository可供使用,因此使用时需要手动将其安装到本地repository. java memcached client ...
- CentOS7.1 JDK安装 和 CentOS7.1配置yum源
1.卸载自带OPENJDK #查看自身jdk java -verson #查看自身安装的java rpm -qa | grep java #显示如下 python-javapackages-3.4. ...
- 微信公众平台 Premature end of file
今天在研究微信公众平台 自动接收发送消息的时候,在如下代码: public String processRequest(HttpServletRequest request) { String res ...
- TextView设置样式的3种方式
1,直接在<TextView>中设置 <TextView android:id="@+id/tv_badge_view_count" android:layout ...