PyLons 请求生命周期

本文对 PyLons 内部调用过程的大致轮廓进行了简单的勾勒.

首先通过命令 paster create --template=PyLons yourproject 创建一个项目. 然后 ==>

" yourproject_dir::command "

# 读取配置文件并启动服务器和应用程序
paster serve development.ini  ==>

" yourproject_dir::development.ini "

#PasteScript 的命令会通过配置文件中指定的 egg 的 entry_points 找到相应的对象
[server:main]
# 指定 paster serve 使用的 web 服务器
use = egg:Paste#http  
[app:main]
use = egg:yourproject  ==>

" yourproject_dir/setup.py "

   1 entry_points="""
   2     [paste.app_factory]
   3     main=yourproject:make_app  ==>
   4     ...
   5 """

" yourproject.__init__.py "

   1 from yourproject.config.middleware import make_app  ==>

" yourproject.config.middleware.py "

   1 def make_app(...):
   2     ...
   3     # 核心 app
   4     app = PyLons.wsgiapp.PyLonsApp(config)  ==>
   5     app = ConfigMiddleware(app, ... )
   6     # YOUR MIDDLEWARE
   7     # 将 HTTPExceptions 转换成 HTTP responses
   8     app = httpexceptions.make_middleware(app, ... )
   9     app = ErrorHandler(app, ... )
  10     # 处理静态文件
  11     static_app = StaticURLParser(...)
  12     # 处理 webhelpers 中使用到的 javascript 文件
  13     javascripts_app = StaticJavascripts()
  14     # 该中间件的作用是: 对列表中的 app 一个一个尝试, 如果 app 产生 404 错误则继续试下一个
  15     app = Cascade([static_app, javascripts_app, app])
  16     app = ErrorDocuments(app, ... )
  17     # 
  18     app = RegistryManager(app)
  19     return app

" PyLons.wsgiapp.py "

   1 class PyLonsApp(object):
   2     def __init__(self, ...):
   3         self.app = PyLonsBaseWSGIApp(... ) ==>
   4     def __call__(self, environ, start_response):
   5         ...
   6         return self.app(environ, start_response)

" PyLons.wsgiapp.py "

   1 class PyLonsBaseWSGIApp(object):
   2     def __init__(self ... )
   3         ...
   4     def __call__(self, environ, start_response):
   5         #正常情况下大致执行流程:
   6         self.setup_app_env(...)
   7         req = PyLons.request._current_obj()
   8         # 通过 url dispatcher (routes) 找到相应 controller
   9         controller = self.resolve(environ, start_response)
  10         # 执行该 controller
  11         response = self.dispatch(controller, environ, start_response)
  12         status, response_headers, content = response.wsgi_response()
  13         start_response(status, response_headers)
  14         return content
  15         ...
  16 
  17     def dispatch(self, controller, environ, start_response):
  18         # 如果是 class, 则实例化之
  19         if not hasattr(controller, '__class__') or \
  20             getattr(controller, '__class__') == type:
  21             controller = controller()
  22         
  23         # 把它当个 wsgi application 调用之
  24         return controller(environ, start_response) ==>

" PyLons.controllers.py "

   1 class Controller(object):
   2     ...
   3     def _dispatch_call(self):
   4         """将请求分发到具体函数"""
   5         action = self._req.environ['PyLons.routes_dict'].get('action')
   6         action_method = action.replace('-', '_')
   7         func = getattr(self, action_method, None)
   8         if isinstance(func, types.MethodType):
   9             response = self._inspect_call(func)
  10         else:
  11             if asbool(CONFIG['global_conf'].get('debug')):
  12                 raise NotImplementedError('Action %s is not implemented' % action)
  13             else:
  14                 response = PyLons.Response(code=404)
  15         return response
  16 
  17 class WSGIController(Controller):
  18     ...
  19     def __call__(self, environ, start_response):
  20         self.start_response = start_response
  21         match = environ['PyLons.routes_dict']
  22         self._req = PyLons.request._current_obj()
  23         
  24         # 不调用私有方法
  25         if match.get('action').startswith('_'):
  26             return PyLons.Response(code=404)
  27         
  28         if hasattr(self, '__before__'):
  29             self._inspect_call(self.__before__)
  30         # 此方法请看上面的 Controller 类
  31         response = self._dispatch_call()
  32         if hasattr(self, '__after__'):
  33             self._inspect_call(self.__after__)
  34         
  35         if hasattr(response, 'wsgi_response'):
  36             # 估计返回的是 paste.wsgiwrappers.WSGIResponse 
  37             status, response_headers, content = response.wsgi_response()
  38             start_response(status, response_headers)
  39         
  40             # 如果是在测试, 将 response 放到测试环境中去
  41             if environ.get('paste.testing'):
  42                 environ['paste.testing_variables']['response'] = response
  43             response = content
  44         
  45         # 看来是个 WSGI应用程序 的 Response
  46         return response
  47 
  48 class RPCController(object):
  49     ...

结论

从中我们大致可以看出 PyLons 扩展的潜力:

PyLons/call-cycle (last edited 2009-12-25 07:09:39 by localhost)