[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()
执行之,问题解决.