[Pyramid 杂记]pyramid.config.Configurator.scan()的实现方式

Python Pyramid交流QQ群: 220128626,欢迎加入.

 

由于是随笔记录平时的思考学习的结果,比较琐碎,格式就不弄了.如果以后要写学习记录什么的,格式再弄好一点.^_^

 

问题产生的原因:

跟着官方的新手教程在学习Pyramid,使用pcreate -s starter MyProject命令生成项目,想调试一下于是修改了下myproject/__init__.py,如下:

from pyramid.config import Configurator
from wsgiref.simple_server import make_server


def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.scan()
    #return config.make_wsgi_app()
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 6543, app)
    server.serve_forever()
   
if __name__ == '__main__':
    main(None)

但是直接运行__init__.py,访问服务器的时候,确报出不能找到"/"路径.考虑可能是config.scan()没有找到view的配置.

回顾下 scan()的介绍:
A scan of a module or a package and its subpackages for decorations happens when the pyramid.config.Configurator.scan() method is invoked: scanning implies searching for configuration declarations in a package and its subpackages.

这里明明介绍会扫描subpackages的么,怎么可能没发现.于是开始debug scan()方法.

def scan(self, package=None, categories=None, onerror=None, ignore=None,
             **kw):

scan方法的第一个参数可以指定package,如果不指定则调用caller_package()方法找到调用scan()方法的代码所属的模块(注意: 是代码,并不一定是指方法.)

caller_package()方法的实现原理是调用sys._getframe方法获得调用scan()方法的代码所属的模块(方法执行环境的global命名空间中包含'__name__'变量,值为模块名或'__main__').

然后,继续调试,发现一段代码如下:

......................................
......................................
if hasattr(package, '__path__'): # package, not module
    results = walk_packages(package.__path__, package.__name__+'.',
                            onerror=onerror, ignore=_ignore)
......................................
......................................

我擦勒,恍然大悟. 以前记录的__path__变量的含义:

Packages support one more special attribute, __path__. This is initialized to be a list containing the name of the directory holding the package's __init__.py before the code in that file is executed. This variable can be modified; doing so affects future searches for modules and subpackages contained in the package.
包支持一个另为特殊的变量, __path__ 。 在包的 __init__.py 文件代码执行之前,该变量初始化一个目录名列表。该变量可以修改,它作用于包中的子包和模块的搜索功能。
While this feature is not often needed, it can be used to extend the set of modules found in a package.
这个功能可以用于扩展包中的模块集,不过它不常用。

原来直接执行__init__.py, 它并未被当做一个package来处理,没有子包,scan()怎么可能搜索的到.

修改代码,在myproject文件外,建立文件myproject.py.(想必pserve命令也是这样处理的):
from myproject import main
from wsgiref.simple_server import make_server


app = main(None)
server = make_server('0.0.0.0', 6543, app)
server.serve_forever()

执行之,问题解决.

posted @ 2012-03-13 23:56  左奕  阅读(610)  评论(0编辑  收藏  举报