flask的flask_script和Manager的深入理解

flask的flask_script和Manager的深入理解,第1张

概述@ TOC flask中Manager源码如下所示: class Manager(object): """ Controller class for handling a set of commands. Typical usage:: class Print(Command): def run(self): @ TOC
flask中Manager源码如下所示:

class Manager(object):    """    Controller class for handling a set of commands.    Typical usage::        class Print(Command):            def run(self):                print "hello"        app = Flask(__name__)        manager = Manager(app)        manager.add_command("print",Print())        if __name__ == "__main__":            manager.run()    On command line::        python manage.py print        > hello

从上面我们我可以看到, 我们定义了一个类继承Command,并且重写了run方法。就可以在命令行执行了,也就是说Command为我们提供一个接口,run方法中内容都会被命令行所执行。
那么,现在看下Command又为我们做了什么, 源码如下所示:

class Command(object):    """    Base class for creating commands.    :param func:  Initialize this command by introspecting the function.    """    option_List = ()    help_args = None    def __init__(self,func=None):        if func is None:            if not self.option_List:                self.option_List = []            return        args,varargs,keywords,defaults = inspect.getargspec(func)        if inspect.ismethod(func):            args = args[1:]        options = []        # first arg is always "app" : ignore        defaults = defaults or []        kwargs = dict(izip(*[reversed(l) for l in (args,defaults)]))        for arg in args:            if arg in kwargs:                default = kwargs[arg]                if isinstance(default,bool):                    options.append(Option(‘-%s‘ % arg[0],‘--%s‘ % arg,action="store_true",dest=arg,required=False,default=default))                else:                    options.append(Option(‘-%s‘ % arg[0],type=text_type,default=default))            else:                options.append(Option(arg,type=text_type))        self.run = func        self.__doc__ = func.__doc__        self.option_List = options    @property    def description(self):        description = self.__doc__ or ‘‘        return description.strip()    def add_option(self,option):        """        Adds Option to option List.        """        self.option_List.append(option)    def get_options(self):        """        By default,returns self.option_List. OverrIDe if you        need to do instance-specific configuration.        """        return self.option_List    def create_parser(self,*args,**kwargs):        func_stack = kwargs.pop(‘func_stack‘,())        parent = kwargs.pop(‘parent‘,None)        parser = argparse.ArgumentParser(*args,add_help=False,**kwargs)        help_args = self.help_args        while help_args is None and parent is not None:            help_args = parent.help_args            parent = getattr(parent,‘parent‘,None)        if help_args:            from flask_script import add_help            add_help(parser,help_args)        for option in self.get_options():            if isinstance(option,Group):                if option.exclusive:                    group = parser.add_mutually_exclusive_group(                        required=option.required,)                else:                    group = parser.add_argument_group(                        Title=option.Title,description=option.description,)                for opt in option.get_options():                    group.add_argument(*opt.args,**opt.kwargs)            else:                parser.add_argument(*option.args,**option.kwargs)        parser.set_defaults(func_stack=func_stack+(self,))        self.parser = parser        self.parent = parent        return parser    def __call__(self,app=None,**kwargs):        """        Handles the command with the given app.        Default behavIoUr is to call ``self.run`` within a test request context.        """        with app.test_request_context():            return self.run(*args,**kwargs)    def run(self):        """        Runs a command. This must be implemented by the subclass. Should take        arguments as configured by the Command options.        """        raise NotImplementedError

下面分析下执行过程:
1、其他函数是对options[列表]的内容进行增删查 *** 作
2、create_parser函数创建了命令行解析对象parser = argparse.ArgumentParser(*args,**kwargs) ,获取options中获取并保存options中数据和help_args中数据,以及parser.set_defaults(func_stack=func_stack+(self,)) 将Command自己添加到parser中参数中。
3,在flask应用代码中我们添加例如manager.add_command("db",Print())的代码,传入了Command的实例对象, 而add_command创建了Command的实例对象并保存在slef._commands的namespace中或者key_value值中。

备注>>>在flask应用代码中我们添加例如manager.add_command("db",MigrateCommand)的代码,传入了Manager的实例对象MigrateCommand- - - -另外一个Manager对象(此对象,已经添加了添加了迁移等命令,后面会和当前这个flask应用中manager对象建立关联self.parent)

4,call方法中显示,当Command的实例对象被调用的时候,就会被执行(此时,引入app实例的上下文,并执行了run方法)。那么此时,我们就只要去寻找Command实例是何时被调用的

此时Manage对象包装app,并执行了自己的run方法.如下所示.

run方法中通过sys.argv接收了命令行参数,并把参数提交给slef.handle执行。
而handle方法中创建app_parser = self.create_parser(prog)(此函数获取到Commad对象),获取了所有的app_parser的信息(func和 args和config)。

parser什么时候被执行?

此时而app_parser依然是argparse中ArgumentParser对象。
依然是在Manage的create_parser方法中,执行了app_namespace,remaining_args = app_parser.parse_kNown_args(args),方法内又调用了_parse_kNown_args

此处是重点:_parse_kNown_args中,内部函数consume_optional先调用self._option_string_actions通过string映射action类,另一方面调用了内部函数take_action,创建action的实例对象(如上面Command的实例对象就是此时被创建)。

app_namespace.dict中可以获取到func_stack,
最后遍历for handle in func_stack:,并执行handle,handle可能是Command实例对象,调用后,执行call方法,执行run方法,也可能是func函数,直接被执行。

def run(self,commands=None,default_command=None):        """        Prepares manager to receive command line input. Usually run        insIDe "if __name__ == "__main__" block in a Python script.        :param commands: optional dict of commands. Appended to any commands                         added using add_command().        :param default_command: name of default command to run if no                                arguments passed.        """        if commands:            self._commands.update(commands)        # Make sure all of this is Unicode        argv = List(text_type(arg) for arg in sys.argv)        if default_command is not None and len(argv) == 1:            argv.append(default_command)        try:            result = self.handle(argv[0],argv[1:])        except SystemExit as e:            result = e.code        sys.exit(result or 0)
总结

以上是内存溢出为你收集整理的flask的flask_script和Manager的深入理解全部内容,希望文章能够帮你解决flask的flask_script和Manager的深入理解所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1197774.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存