pecan源码阅读(一)

pecan源码目录

在这里插入图片描述

创建pecan工程

pecan create test

创建pecan工程用到了bin下的pecan脚本

// bin/pecan
#!/usr/bin/env python
if __name__ == '__main__':
    from pecan.commands import CommandRunner
    CommandRunner.handle_command_line()

调用了pecan/commands/base.py下的CommandRunner类中的handle_command_line()方法

//具体处理命令
def run(self, args):
    ns = self.parser.parse_args(args)//解析参数
    self.commands[ns.command_name]().run(ns)//执行命令,相当于执行commands下相应模块中的run方法

@classmethod
def handle_command_line(cls):
    runner = CommandRunner()//实例化该对象时,加载commands文件夹下定义的名命令
    runner.run(sys.argv[1:])
// pecan/commands/base.py
//加载command的方法,entry point在setup.py里面注册了
def load_commands(self):
    for ep in pkg_resources.iter_entry_points('pecan.command'):
        log.debug('%s loading plugin %s', self.__class__.__name__, ep)
        if ep.name in self.commands:
            warn(
                "Duplicate entry points found on `%s` - ignoring %s" % (
                    ep.name,
                    ep
                ),
                RuntimeWarning
            )
            continue
        try:
        	//该方法是去加载模块中含有run方法的类
            cmd = ep.load()
            cmd.run  //确保加载的类有run方法
        except Exception as e:  # pragma: nocover
            warn("Unable to load plugin %s: %s" % (ep, e), RuntimeWarning)
            continue
        self.add({ep.name: cmd})//添加到self.commands字典里面,上面的run运行时,从字典中取出类,实例化,然后调用run方法

可以看到,pecan创建工程的过程和django类似(其实基本所有的python web框架都是一样的)

下面来看看创建工程具体做了什么工作

// pecan/commands/create.py

class ScaffoldManager(object):
    def __init__(self):
        self.scaffolds = {}
        self.load_scaffolds()
    def load_scaffolds(self):
    	//加载在setup.py文件中注册了的类
        for ep in pkg_resources.iter_entry_points('pecan.scaffold'):
            log.debug('%s loading scaffold %s', self.__class__.__name__, ep)
            try:
                cmd = ep.load()
                cmd.copy_to	//确保有copy_to方法
            except Exception as e:  # pragma: nocover
                warn(
                    "Unable to load scaffold %s: %s" % (ep, e), RuntimeWarning
                )
                continue
            self.add({ep.name: cmd})
    def add(self, cmd):
        self.scaffolds.update(cmd)


class CreateCommand(BaseCommand):
	//通过实例化该对象,加载pecan/scaffolds下的BaseScaffold和RestAPIScaffold类,加载方法和加载command方法一样
    manager = ScaffoldManager()
    arguments = ({
        'name': 'project_name',
        'help': 'the (package) name of the new project'
    }, {
        'name': 'template_name',
        'metavar': 'template_name',
        'help': 'a registered Pecan template',
        'nargs': '?',
        'default': DEFAULT_SCAFFOLD,//值为base,会调用BaseScaffold的实例
        'choices': manager.scaffolds.keys()
    })
    //该方法会首先执行
    def run(self, args):
        super(CreateCommand, self).run(args)
        // self.manager.scaffolds为{'rest-api': <class 'pecan.scaffolds.RestAPIScaffold'>, 'base': <class 'pecan.scaffolds.BaseScaffold'>}
        //具体由RestAPIScaffold和BaseScaffold去创建工程
        self.manager.scaffolds[args.template_name]().copy_to(
            args.project_name	//项目名:test
        )

注:通过上面的代码可以知道,默认创建工程时使用的是BaseScaffold类,创建的是一般的pecan工程,而要创建restful的pecan工程,则需要使用下面的方式创建

pecan create test rest-api

BaseScaffold和RestAPIScaffold调用copy_to(project_name)方法去创建工程,主要工作就是根据传入的项目名创建目录,拷贝文件等,pecan/scaffolds模块中放置了相关的模板文件
在这里插入图片描述
至此,一个pecan工程就创建完毕。

运行pecan工程

运行方式:

pecan serve config.py

和创建工程一样,运行时调用了pecan/commands/create.py模块的方法。

def run(self, args):
    super(ServeCommand, self).run(args)
    app = self.load_app() // 创建一个app
    self.serve(app, app.config) // 部署app

众所周知,要运行一个python的web服务,需要两个条件:
1.application
2.wsgi server
上面的load_app()方法创建了一个application(会调用到core.py里面的load_app()方法)

// pecan/core.py
def load_app(config, **kwargs):
    from .configuration import _runtime_conf, set_config
    //根据配置文件初始化配置
    set_config(config, overwrite=True)
    for package_name in getattr(_runtime_conf.app, 'modules', []):
        module = __import__(package_name, fromlist=['app'])
        //项目工程创建好后,有个test/test/app.py文件,里面的setup_app(config)具体来创建app
        if hasattr(module, 'app') and hasattr(module.app, 'setup_app'):
        	//这里开始创建一个app
            app = module.app.setup_app(_runtime_conf, **kwargs)
            app.config = _runtime_conf
            return app
    raise RuntimeError(
        'No app.setup_app found in any of the configured app.modules'
    )

// test/test/app.py
def setup_app(config):
    model.init_model()	//创建app时,初始化model,一般在这实现orm映射
    app_conf = dict(config.app)
    //	test/conifg.py文件中有app配置项,定义了app的重要内容
    return make_app(
        app_conf.pop('root'),
        logging=getattr(config, 'logging', {}),
        **app_conf
    )

//	pecan/__init__.py
def make_app(root, **kw):
  	...
  	// root是test/config.py中app项里面配置的,作为路由的入口
    app = Pecan(root, **kw)
	...
    return app

app其实就是一个Pecan实例。

对于wsgi server,下面的代码可以看出,pecan使用了python内置的simple_server

// pecan/commands/serve.py
def serve(self, app, conf):
      if self.args.reload:
          try:
          		//使用了watchdog,用于修改文件后自动部署(暂不做讲解)
              self.watch_and_spawn(conf)
          except ImportError:
              print('The `--reload` option requires `watchdog` to be '
                    'installed.')
              print('   $ pip install watchdog')
      else:
      		//这里就是具体部署app的方法
          self._serve(app, conf)
 
def _serve(self, app, conf):
	// 引入python内置simple_server 
   from wsgiref.simple_server import make_server
   host, port = conf.server.host, int(conf.server.port)
   srv = make_server(
       host,
       port,
       app, //创建的app
       handler_class=PecanWSGIRequestHandler,//处理器
   )
   print('Starting server in PID %s' % os.getpid())
   if host == '0.0.0.0':
       print(
           'serving on 0.0.0.0:%s, view at http://127.0.0.1:%s' %
           (port, port)
       )
   else:
       print("serving on http://%s:%s" % (host, port))
   try:
   		// 运行web服务
       srv.serve_forever()
   except KeyboardInterrupt:
       # allow CTRL+C to shutdown
       pass

至此,一个python web服务就运行起来了。

下一篇将介绍pecan工程配置文件和路由。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值