如何使用Paste.Deploy

转自:http://bingotree.cn/?p=100

1.Paste Deploy的一个组件,但是并不依赖于Paste的其它组件。其可以看成是一个独立的包。其主要用于通过一个配置文件完成WSGI应用和服务器的构建。对于一个不怎么了解Python的人来说,只要知道了这个配置文件如何编写,那么也能写出一个符合WSGI标准的应用。这样说可能还是有点抽象,下面看了例子就清楚了。

2.安装PasteDeploy


1

2

3

[[email protected]_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 = [email protected]

[app:main]

use = ...

set admin_email = [email protected]

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()

时间: 2024-10-28 10:05:43

如何使用Paste.Deploy的相关文章

Python Paste.deploy 笔记

首先python paste是一个WSGI工具包,在WSGI的基础上包装了几层,让应用管理和实现变得方便.说实话,Python Paste的文档做的真差劲!加之python代码可读性本来就不怎么滴,真费劲. paste.deploy关键部分留个抓印: 1)python paste.deploy不能只装个paste.deploy包就可以工作了,还需要paste.script包 2)python paste.deploy中loadapp给的路径可用os.path.abspath(配置文件相对路径)得

keystone源码分析(一)——Paste Deploy的应用

本keystone源码分析系列基于Juno版Keystone,于2014年10月16日随Juno版OpenStack发布. Keystone作为OpenStack中的身份管理与授权模块,主要实现系统用户的身份认证.基于角色的授权管理.其他OpenStack服务的地址发现和安全策略管理等功能.Keystone作为开源云系统OpenStack中至关重要的组成部分,与OpenStack中几乎所有的其他服务(如Nova, Glance, Neutron等)都有着密切的联系.同时,Keystone作为开源

自己使用python webob,paste.deploy,wsgi总结

paste.deploy就是一个可以配置wsgi_app的工具,可以让服务器运行时,按照配置文件执行一系列的程序.需要使用.ini配置文件. (1)这里补充一下当时没看到的配置文件 1.[app:main]的意识是只有一个app,所以就叫main,其实叫别的也无所谓. use=egg:MyAPP   egg其实是一个程序包,是需要单独安装的东西.egg包是目前最流行的python应用打包部署方式 2.[composite:main]                      composite是

paste deploy初探

这段时间刚着手开始研究Openstack Swift源码,为后续开发做准备. Swift依据python WSGI规范.WSGI(Web Server Gateway Interface)是Python应用程序或框架与Web服务器之间的一种接口,定义了一套借口来实现服务器与应用端的通信规范.按照一套规范,应用端想要通信,很简单,只需要实现一个接受两个参数的,含有__call__方法并返回一个可遍历的含有零个或者多个string结果的python对象.  而paste.deploy(Paste D

paste deploy 学习笔记

谈到WSGI,就免不了要了解paste,其中paste deploy是用来发现和配置WSGI应用的一套系统,对于WSGI应用的使用者而言,可以方便地从配置文件汇总加载WSGI应用(loadapp):对于WSGI应用的开发人员而言,只需要给自己的应用提供一套简单的入口点即可. paste deploy的官方介绍在这里,其发布在Pypi上的发行包在这里下载.借助Python的pypi包管理机制,我们可以非常方便地安装PasteDeploy: # pip install PasteDeploy 既然P

Paste Deployment简介: **-api-paste.ini的解析

1 什么是Paste Deployment Paste Deployment是一种机制或者说是一种设计模式,它用于在应用WSGI Application和Server提供一个联系的桥梁,并且为用户提供一个接口,当配置好Paste Deployment之后,用户只需调用loadapp方法就可以使用现有的WSGI Application,而保持了WSGI Application对用户的透明性. 2 Paste Deployment中section简单描述 在paste deploy中,为了区分不同类

nova分析(3)—— nova-api

nova-api是nova对外提供Restful API的服务,Horizon.novaclient等均通过该api与nova进行通信. nova其实对外提供了多个api服务,包括下面这些服务: nova-apinova-api-ec2nova-api-metadatanova-api-os-compute 其中,nova-api用于启动其他三个服务.下面逐个分析下. nova-api 入口在 nova.cmd.api:main ,主要是基于WSGI.PasteDeploy.Webob.Rout

ImportError: No module named app_factory

1 ImportError: No module named app_factory 在运行python的一个wsgi相关的程序时,出现下列错误: [email protected]:~/python$ python wsgi_paste.py Traceback (most recent call last): File "wsgi_paste.py", line 13, in <module> wsgi_app = loadapp('config:'+ini_path)

nova api源码分析(二)

转载于:http://www.it165.net/pro/html/201407/17020.html (经过部分编辑) 一.使用到的库或组件如下: paste.deploy 用来解析/etc/nova/api-paste.ini文件,加载用于服务的wsgi app.它的功能有: 1.api-paste.ini中配置多个wsgi app,deploy可根据传入的app name加载指定的wsgi app: deploy.loadapp("config:/etc/nova/api-paste.in