Paste Deployment

介绍

Paste Deployment 是用于查找和配置WSGI应用程序和服务器的系统。 对于WSGI应用程序使用者来说,Paste Deployment提供了一个简单的函数(loadapp),用于从配置文件或Python Egg加载WSGI应用程序。 对于WSGI应用程序提供者来说,Paste Deployment只要求你的应用程序有一个简单的入口点,这样应用程序用户就不需要公开应用程序的实现细节。

安装

pip install PasteDeploy

使用介绍

与 Paste Deploy的主要交互是通过其配置文件进行的。 了解使用 paster serve命令功能查看 https://pastescript.readthedocs.io/en/latest/#paster-serve

配置文件解说

配置文件由各个不同的部分组成。 Paste Deploy会解析包含前缀的块,格式如:app:main或filter:errors,在冒号后面的是块的名字,前面的是类型(type)。

块内容格式是一种简单的 INI format :name = value。 可以通过缩进后续行来扩展该值。 #是一个注释。

通常可能会有一两个名为“main”的部分:一个应用程序部分([app:main])和一个服务器部分([server:main])。 [composite:...]表示分派给多个应用程序的东西 。

下面是一个典型的配置文件,它还展示了如何挂载多个应用程序 :

[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

现在我将详细解释每个部分:

[composite:main]
use = egg:Paste#urlmap
/ = home
/blog = blog
/cms = config:cms.ini

这是composite块, 它将请求分发给其他应用程序。 use = egg:Paste#urlmap是指将请求进行分发的路由映射使用Paste包中的urlmap模块。 urlmap是一个特别常见的 composite应用程序-- 它使用路径前缀将请求映射到另一个应用程序。 如例子所示这些应用程序包括“home”、“blog”、“wiki”和“config:cms.ini”。 最后一个分发的作用是将文件指向同目录 cms.ini 文件。

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

egg:Paste#static 是另一个简单的应用程序,在本例中,它只提供非动态文件。 它需要一点配置: document_root。 可以使用变量替换,它将使用%(var_name)s记从[DEFAULT](区分大小写!)中提取变量。 特殊变量%(here)s 是包含配置文件的目录; 你应该用它来代替相对应的文件名 (依赖于当前目录,可以根据服务器的运行方式进行更改) 。

[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]的设置应用了过滤器。被过滤的应用程序由next(指向下一section)指示下一步egg:Authentication#auth 过滤器实际上并不存在,但可以想象它会登录用户并检查权限。

[app:blogapp] 部分只是对BLogApp(可能通过pip install BlogApp安装)应用程序的引用,database是传递给BLogApp的一个配置

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

这一节与前一节类似,但有一个重要的区别。 它直接引用mywiki.main模块的application变量, 而不是egg中的入口点。 引用由两个部分组成,由冒号分隔。 左侧是模块的全名,右侧是变量的路径,它是相对于包含模块的Python表达式。

基本用法

使用 Paste Deployment的基本方法是加载WSGI应用程序。 许多Python框架现在都支持WSGI,因此为这些框架编写的应用程序应该是可用的。

主要功能是 paste.deploy.loadapp。 这将加载给定的URI应用程序。 如下所示:

from paste.deploy import loadapp
wsgi_app = loadapp('config:/path/to/config.ini')

目前支持两种URI格式:config:和egg:。

config: URIs

使用config:的uri:指向配置文件。 如果将 relative_to参数传递给loadapp(),则这些文件名可以是相对的。

注意: 文件名从来不被认为是相对于当前工作目录的,因为这是一个不可预测的位置。 通常,当URI具有上下文时,它将被视为相对于该上下文;例如,如果在另一个配置文件中有一个config: URI,则该路径被认为是相对于包含该配置文件的目录的。

配置格式

配置文件采用INI格式。如下是一个简单的格式例子:

[section_name]
key = value
another key = a long value
    that extends over multiple lines

所有值都是字符串(不需要引号)。keys和section名是区分大小写的, 可能包含标点符号和空格(尽管keys和values都去掉了前导空格和后置空格)。 行可以用前导空格继续 。

以#开头则是注释的内容。

Applications

可以在一个文件中定义多个应用程序;每个应用程序都有自己的section。 即使只有一个应用程序,也必须将其放在一个section中。 定义 application 的每个 section名都应该以app:作为前缀。 "main" section (仅定义一个应用程序时) 将进入[app:main]或[app]。

有两种方法可以指示应用程序的Python代码。 第一种是引用另一个URI或名称:

[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

乍一看,这似乎毫无意义;只是一种指向另一个位置的方法。 但是,除了从该位置加载应用程序之外,还可以添加或更改配置。

另一种定义应用程序的方法是准确地指向某些Python代码(如下):

[app:myapp]
paste.app_factory = myapp.modulename:app_factory

必须提供一个明确的协议(在本例中是 paste.app_factory)。在此例子中会加载myapp.modulename模块,并引用 app_factory对象。

关于更多工厂的定义细节请查看 Defining Factories

Configuration

除了use(或协议名称)外,通过keys进行配置。 任何在section找到的keys都将作为参数传递给factory。如一所示:

[app:blog]
use = egg:MyBlog
database = mysql://localhost/blogdb
blogname = This Is My Blog!

可以在其它sections对它进行override,如:

[app:otherblog]
use = blog
blogname = The other face of my blog

通过这种方式,一些设置可以在一个通用配置文件中定义 (如果有 use = config:other_config_file) , 或者您可以通过添加一个section来发布多个(更专门化的)应用程序。

Global Configuration

通常许多应用程序共享相同的配置。 虽然您可以通过使用其他配置部分和重写值来实现这一点,但通常您希望对一组不同的配置值执行此操作。 通常 applications不能接受“额外的”配置参数;使用全局配置,可以给 applications 传递更多的参数,如电子邮件等。

Applications是单独传递全局配置的,因此它们必须明确地从中提取值;通常,当没有传递本地配置时,全局配置作为默认值的基础。

应用于文件中定义的每个 application的全局配置应该放在名为[DEFAULT]的section中。

也可以在自已的section内override全局配置,如下:

[DEFAULT]
admin_email = webmaster@example.com

[app:main]
use = ...
set admin_email = bob@example.com

Composite Applications

"Composite" 应用程序的行为类似于应用程序,但由其他应用程序组成。 一个最普遍的例子是URL映射器,您可以将应用程序挂载在不同的URL路径上。如下所示:

[composite:main]
use = egg:Paste#urlmap
/ = mainapp
/files = staticapp

[app:mainapp]
use = egg:MyApp

[app:staticapp]
use = egg:Paste#static
document_root = /path/to/docroot

Other Objects

除了使用app:定义应用程序section外,还可以在配置文件中使用server:和filter:前缀来定义过滤器和服务器。 使用loadserver和loadfilter加载这些程序。 配置的工作原理是一样的;只是会得到不同种类型的对象。

Filter Composition

有几种方法可以将filters应用于applications。这主要取决于有多少个 filters,以及应用它们的顺序。

第一种方法是使用filter-with设置,比如:

[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...

另外,存在两种特殊的section类型将过滤器应用于应用程序: [filter-app:...][pipeline:...]。 这两个sections都定义了应用程序,因此可以在需要应用程序的任何地方使用。

filter-app定义了一个过滤器(就像在[filter:...]section 定义的一样),特殊键next向要应用过滤器的应用程序。

pipeline: 在需要应用多个过滤器时使用。 它需要配置一个pipeline键(或加上任何想要重载的全局配置)。 pipeline是应用程序结束的过滤器列表,如下:

[pipeline:main]
pipeline = filter1 egg:FilterEgg#filter2 filter3 app

[filter:filter1]
# ...

获取配置 Getting Configuration

如果想在不创建应用程序的情况下获得配置,可以使用appconfig(uri)函数,该函数与loadapp()函数类似,只是它返回的是字典类型的配置。

全局和本地配置都会被组合到一个字典中, 但是您可以使用.local_conf和.global_conf属性来查看。

egg

Python Eggssetuptoolsdistribute 生成的一种发行版和安装格式 ,用于将元数据添加到正常的python包中(以及其他内容)。

定义Factories

这允许您指向工厂(遵守我们提到的特定协议)。 但是,除非您可以为应用程序创建工厂,否则这没有多大用处。

有几个协议: paste.app_factory, paste.composite_factory, paste.filter_factorypaste.server_factory。 它们都需要一个可调用的东西(比如函数、方法或类)。

paste.app_factory

应用程序是最常见的。 定义app工厂如下所示:

def app_factory(global_config, **local_conf):
    return wsgi_app

global_config 是一个字典, local配置是作为keyword参数传递进来。此方法应返回一个 WSGI application.。

paste.composite_factory

Composites只是稍微复杂一点 :

def composite_factory(loader, global_config, **local_conf):
    return wsgi_app

loader参数是一个对象,它有两个有趣的方法。 get_app(name_or_uri, global_conf=None) 返回给定名称的WSGI应用程序 。 get_filterget_server 方法与前面的方法工作方式一样。

一个更有趣的例子可能是一个composite工厂。 例如,“ pipeline ”应用程序 :

def pipeline_factory(loader, global_config, pipeline):
    # space-separated list of filter and app names:
    pipeline = pipeline.split()
    filters = [loader.get_filter(n) for n in pipeline[:-1]]
    app = loader.get_app(pipeline[-1])
    filters.reverse() # apply in reverse order!
    for filter in filters:
        app = filter(app)
    return app

使用方式如下:

[composite:main]
use = <pipeline_factory_uri>
pipeline = egg:Paste#printdebug session myapp

[filter:session]
use = egg:Paste#session
store = memory

[app:myapp]
use = egg:MyApp

paste.filter_factory

过滤器工厂有点像应用程序工厂(相同的签名),但过滤器工厂返回过滤器外。过滤器是可调用的,它接收WSGI应用程序作为唯一参数并返回该应用程序的已过滤版本。

下面是一个过滤器的示例,它检查远程用户CGI变量是否设置,从而创建一个非常简单的身份验证过滤器 :

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']

paste.filter_app_factory

它和 paste.filter factory有点相似, 但它还需要接收wsgi应用程序参数,并返回一个wsgi应用程序。 所以上面的例子修改后如下:

class AuthFilter(object):
    def __init__(self, app, global_conf, req_usernames):
        # ...

然后AuthFilter将在 filter_app_factory里提供服务 (在本例中,req_usernames是必需的本地配置键)。

paste.server_factory

它接收与 applications和filters相同的签名,但返回一个server。

server 是可调用的,它接收一个参数,即WSGI应用程序。 然后它为应用程序服务。 例子如下:

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的实现留给了用户。

paste.server_runner

除了 wsgi_app 作为第一个参数传递, server应该立即运行外其它的都与paste.server factory一样。

使用例子

openstack服务项目都是使用paste来部署wsgi app的,可以参考nova-api的api-paste.ini例子,查看api-paste.ini解析

 

 

 

 

 

转载于:https://my.oschina.net/jennerlo/blog/3004127

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值