paste.deploy学习笔记

http://blog.lightcloud.cn/?p=183

Pasted Deployment是一套查找和配置WSGI应用和服务的系统。向WSGI application(WSGI应用,可调用对象)的用户提 供了一个简单的函数(loadapp)来从配置文件或是python的egg包中加载WSGI application。调用WSGI application的程序只要求你的程序提供一个简单的单独的访问入口,所以application发布者并不需要暴露application的内部 的实现细节。

这样的好处是系统管理员可以很容易的安装和管理,并不需要掌握python,或是WSGI Application的细节和它的container。 目前Paste Deployment不需要依赖Paste项目中的其他部分,可以单独做为一个安装包。 Paste Deploy使用MIT协议发布。

Paste Deploy已经发布了1.0版本,是个活跃的开发项目。在1.0版本中,做了很多工作使它向后兼容,会在必要时包含对一些不再推荐使用的功能的警告。

名词解释

  • application:应用,符合WSGI规范的可调用对象,接受参数(environ, start_response),调用start_response返回状态和HTTP消息头,返回结果作为消息体。
  • filter:过滤器,可调用对象,类似python中的装饰器(decorator),接受一个application对象作为参数,返回一个封装后的application。
  • app_factory:可调用对象,接受参数(global_config, **local_conf),返回application对象。
  • composite_factory:可调用对象,接受参数(loader, global_config, **local_conf),loader有几个方法, get_app用于获取wsgi_app, get_filter用于加载filter, 返回application对象。
  • filter_factory:可调用对象,接受参数(global_config, **local_conf),返回filter对象

Paste Deploy最主要的一方面是它定义的entry points(像paste.app_factory)

paste.deploy用的最多的是通过它的配置文件。

配置文件分为不同的段(section),Paste Deply关心的几个段(section)都有前缀,像 app:main 还有 filter:errors————冒号后面的部分是段的名字(name of section),冒号前的部分给出段的类型(type of section)。其他的段(section)会被忽略。

paste配置文件就是普通的INI文件格式,可以使用缩进的多行来作为一行的延续。开头的”#”井号或是”;”分号后面是注释。 格式像下面这样定义

?
1
2
3
4
[section_name]
key = value
another key = a long value
     that extends over multiple lines

所有的值都是字符串(不需要用引号括起来),每个段的名字和段中值的名字都是大小写敏感的,可以包含标点符号和空白符,最后键和值两边的空白符都会被去掉。以空白符开始的行被认为是上一行的延续。

通常会添加两个段,一个叫做main的应用段([app:main])和一个服务段([server:main])。[composite:...]表示转发到多个应用的东西。

下面是一个典型的配置文件使用了paste.urlmap来组合多个应用。

?
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

下面解释详细解释每一段:

?
1
2
3
4
5
6
[composite:main]
use = egg:Paste#urlmap
/ = home
/blog = blog
/wiki = wiki
/cms = config:cms.ini

这是一个composite段,它会转发请求到其他的应用。use = egg:Paste#urlmap 表示使用paste包中的叫做urlmap的 composite applicationurlmap 是一个通用的 composite application —— 它把请求转到其他的应用。这里有几个应用,像”home”, “blog”, “wiki”和”config:cms.ini”。最后一个只是指向同一个文件夹下的cms.ini配置文件。

接下来:

?
1
2
3
[app:home]
use = egg:Paste#static
document_root = %(here)s/htdocs

egg:Paste#static 是另一个简单的应用,处理非动态文件。需要参数 document_root, 指定静态文件根目录。还可以使用变量替换,变量是在[DEFAULT]段中定义的,定义替换变量作用标签 %(var_name)s。上面用到的特殊变量 %(here)s 指这个配置文件所在的文件夹。

接下来,看看

?
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:blog]段是用到应用上的过滤器(filter)。next字段指定了这个filter应用到哪个应用上。

第二个段只是指向BlogApp应用,database会做为参数传递到应用中。

最后

?
1
2
3
[app:wiki]
use = call:mywiki.main:application
database = sqlite:/home/me/wiki.db

这个段和前一个段很像,一个重要的不同点是它直接指向mysiki.main模块中的应用而不是egg包中的入口点(entry point)。指向哪个应用定义由冒号分隔的两部分组成:冒号左边的模块的名字,右边是从模块中引用的应用。

以上就是最常用的功能。

配置文件中的DEFAULT段的选项会被作为全局变量。在其他段中的选项做为局部变量传到相应的application中,如果局部选项中的键和 DEFAULT中的键一样,局部选项中键会被忽略(global_config和local_config中都没有),如果想覆盖全局变量中的键值,使用set字段,如

?
1
2
3
4
5
6
7
8
[DEFAULT]
name = TEST
version = 1.0
 
[app:test]
use = call:test:test
version = 2.0
set name = test

使用loadapp生成test应用时,会调用test.test,和调用app_factory一样,传入global_config和 local_config,global_config中name=test,被局部配置覆盖了,global_config中version还是 1.0,局部配置中没有version。

使用call时是会转成相应的factory(app转成app_factory,filter转成 filter_factory,composite转成composite_factory)但是调用的方法名,只能是函数,不能是类的方法,虽然在代码 注释中写可以导入如”obj.method”,但是其在引入可调用对象时是直接使用getattr会报错,还是不能有点”.”

示例代码如下:test_paste.ini

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[DEFAULT]
name = TEST
version = 1.0
 
[app:test1]
paste.app_factory = test_wsgi:TestApp.factory
version = 2.0
set name = test
 
[app:test2]
use = call:test_wsgi:test2_factory
version = 2.0
set name = test
 
[composite:test3]
use = call:test_wsgi:composite_factory
/ = test
/name = Tony NIU

test_wsgi.py

?
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import os
 
import eventlet
from eventlet import wsgi, listen
from paste import deploy
 
_path = os.path.dirname(__file__)
 
#application object
class TestApp( object ):
     @classmethod
     def factory( cls , global_conf, * * local_conf):
         return cls ()
 
     def __call__( self , env, start_response):
         #print env
         start_response( "200 OK" , ())
         return [ "welcome" ]
 
def test_app( self , env, start_response):
     start_response( "200 OK" , ())
     return [ "welcome" ]
 
test2_factory = TestApp.factory
 
def composite_factory(loader, global_config, * * local_config):
     #print env, start_response, args, kwargs
     return TestApp()
 
def filter_factory(global_config, * * local_config):
     import time
     def fiter(app):
         print "now is %f" % time.time()
         return app
     return filter
 
def main():
     f = "config:%s" % os.path.join(_path, "test_paste.ini" )
     host = "0.0.0.0"
     server_list = [( "test1" , 8001 ),
                     ( "test2" , 8002 ),
                     ( "test3" , 8003 ),]
 
     servers = []
     for app_name, port in server_list:
         _socket = listen((host, port))
         app = deploy.loadapp(f, app_name)
 
         print "%s is starting" % app_name
         servers.append(eventlet.spawn(wsgi.server, _socket, app))
 
     for server in servers:
         server.wait()
 
if __name__ = = '__main__' :
     main()

参考:http://pythonpaste.org/deploy/index.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值