首先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(配置文件相对路径)得到配置文件的绝对路径,否则报找不到relative_to path...没搞明白怎么回事,目前不重要,放过。
3)python paste.deploy中filter,filter_factory,app,app_factory的规范在文档中都没怎么写清楚,我来给你补上吧:
- app是一个callable object,接受的参数(environ,start_response),这是paste系统交给application的,符合
WSGI规范的参数. app需要完成的任务是响应envrion中的请求,准备好响应头和消息体,然后交给start_response处理,并返回响应消息体。
- filter是一个callable object,其唯一参数是(app),这是WSGI的application对象,见(1),filter需要完成的工作是将application包装成另一个application(“过滤”),并返回这个包装后的application。
- app_factory是一个callable object,其接受的参数是一些关于application的配置信息:(global_conf,**kwargs),global_conf是在ini文件中default section中定义的一系列key-value对,而**kwargs,即一些本地配置,是在ini文件中,app:xxx section中定义的一系列key-value对。app_factory返回值是一个application对象
- filter_factory是一个callable object,其接受的参数是一系列关于filter的配置信息:(global_conf,**kwargs),global_conf是在ini文件中default section中定义的一系列key-value对,而**kwargs,即一些本地配置,是在ini文件中,filter:xxx section中定义的一系列key-value对。filter_factory返回一个filter对象
给个例子:
pastedeploylab.ini:
1. [DEFAULT]
2. key1=value1
3. key2=value2
4. key3=values
5. [composite:pdl]
6. use=egg:Paste#urlmap
7. /:root
8. /calc:calc
9. [pipeline:root]
10. pipeline = logrequest showversion
11. [pipeline:calc]
12. pipeline = logrequest calculator
13. [filter:logrequest]
14. username = root
15. password = root123
16. paste.filter_factory = pastedeploylab:LogFilter.factory
17. [app:showversion]
18. version = 1.0.0
19. paste.app_factory = pastedeploylab:ShowVersion.factory
20. [app:calculator]
21. description = This is an "+-*/"
22. paste.app_factory = pastedeploylab:Calculator.factory
pastedeploylab.py
1. '''''
2. Created on 2011-6-12
3. @author: Sonic
4. '''
5. import
6. import
7. from webob import
8. from webob import
9. from paste.deploy import
10. from wsgiref.simple_server import
11. #Filter
12. class
13. def __init__(self,app):
14. self.app = app
15. pass
16. def __call__(self,environ,start_response):
17. print "filter:LogFilter is called."
18. return self.app(environ,start_response)
19. @classmethod
20. def factory(cls, global_conf, **kwargs):
21. print "in LogFilter.factory", global_conf, kwargs
22. return
23. class
24. def __init__(self):
25. pass
26. def __call__(self,environ,start_response):
27. "200 OK",[("Content-type", "text/plain")])
28. return ["Paste Deploy LAB: Version = 1.0.0",]
29. @classmethod
30. def factory(cls,global_conf,**kwargs):
31. print "in ShowVersion.factory", global_conf, kwargs
32. return
33. class
34. def __init__(self):
35. pass
36.
37. def __call__(self,environ,start_response):
38. req = Request(environ)
39. res = Response()
40. "200 OK"
41. "text/plain"
42. # get operands
43. "operator", None)
44. "operand1", None)
45. "operand2", None)
46. print
47. opnd1 = int(operand1)
48. opnd2 = int(operand2)
49. if operator == u'plus':
50. opnd1 = opnd1 + opnd2
51. elif operator == u'minus':
52. opnd1 = opnd1 - opnd2
53. elif operator == u'star':
54. opnd1 = opnd1 * opnd2
55. elif operator == u'slash':
56. opnd1 = opnd1 / opnd2
57. "%s /nRESULT= %d"
58. return
59. @classmethod
60. def factory(cls,global_conf,**kwargs):
61. print "in Calculator.factory", global_conf, kwargs
62. return
63. if __name__ == '__main__':
64. "pastedeploylab.ini"
65. "pdl"
66. "config:%s"
67. 'localhost',8080,wsgi_app)
68. server.serve_forever()
69. pass
使用:
http://127.0.0.1:8080/
输出:
Paste Deploy LAB: Version = 1.0.0
http://127.0.0.1:8080/calc?operator=plus&operand1=12&operand2=23
输出:
UnicodeMultiDict([('operator', u'plus'), ('operand1', u'12'), ('operand2', u'23')])
RESULT= 35
====================================================
进一步猜测filter的使用过程:在paste deploy库中应该有类似这样的一段代码对application进行重组包装:
#
# 假设在ini文件中, 某条pipeline的顺序是filter1, filter2, filter3
# app, 那么,最终运行的app_real是这样组织的:
#
app_real = filter1(filter2(filter3(app)))
# 在app真正被调用的过程中,filter1.__call__(environ,start_response)被首先调用,若某种检查未通过,filter1做出反应;否则交给filter2__call__(environ,start_response)进一步处理,若某种检查未通过,filter2做出反应,中断链条,否则交给filter3.__call__(environ,start_response)处理,若filter3的某种检查都通过了,最后交给app.__call__(environ,start_response)进行处理。