@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
從上面我們我可以看到, 我們定義了一個(gè)類繼承Command, 并且重寫了run方法。就可以在命令行執(zhí)行了, 也就是說(shuō)Command為我們提供一個(gè)接口, run方法中內(nèi)容都會(huì)被命令行所執(zhí)行。
那么,現(xiàn)在看下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],
'--%s' % arg,
dest=arg,
type=text_type,
required=False,
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, *args, **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
下面分析下執(zhí)行過(guò)程:
1、其他函數(shù)是對(duì)options[列表]的內(nèi)容進(jìn)行增刪查操作
2、create_parser函數(shù)創(chuàng)建了命令行解析對(duì)象parser = argparse.ArgumentParser(*args, add_help=False, **kwargs)
,獲取options中獲取并保存options中數(shù)據(jù)和help_args中數(shù)據(jù),以及parser.set_defaults(func_stack=func_stack+(self,))
將Command自己添加到parser中參數(shù)中。
3,在flask應(yīng)用代碼中我們添加例如manager.add_command("db", Print())
的代碼,傳入了Command的實(shí)例對(duì)象, 而add_command創(chuàng)建了Command的實(shí)例對(duì)象并保存在slef._commands的namespace中或者key_value值中。
manager.add_command("db", MigrateCommand)
的代碼,傳入了Manager的實(shí)例對(duì)象MigrateCommand- - - -另外一個(gè)Manager對(duì)象(此對(duì)象,已經(jīng)添加了添加了遷移等命令, 后面會(huì)和當(dāng)前這個(gè)flask應(yīng)用中manager對(duì)象建立關(guān)聯(lián)self.parent)4,call方法中顯示,當(dāng)Command的實(shí)例對(duì)象被調(diào)用的時(shí)候,就會(huì)被執(zhí)行(此時(shí), 引入app實(shí)例的上下文, 并執(zhí)行了run方法)。那么此時(shí),我們就只要去尋找Command實(shí)例是何時(shí)被調(diào)用的
。
run方法中通過(guò)sys.argv接收了命令行參數(shù),并把參數(shù)提交給slef.handle
執(zhí)行。
而handle方法中創(chuàng)建app_parser = self.create_parser(prog)
(此函數(shù)獲取到Commad對(duì)象),獲取了所有的app_parser的信息(func和 args和config)。
此時(shí)而app_parser依然是argparse中ArgumentParser
對(duì)象。
依然是在Manage的create_parser方法中,執(zhí)行了app_namespace, remaining_args = app_parser.parse_known_args(args)
, 方法內(nèi)又調(diào)用了_parse_known_args
此處是重點(diǎn):_parse_known_args中,內(nèi)部函數(shù)consume_optional先調(diào)用self._option_string_actions通過(guò)string映射action類,
另一方面調(diào)用了內(nèi)部函數(shù)take_action,創(chuàng)建action的實(shí)例對(duì)象(如上面Command的實(shí)例對(duì)象就是此時(shí)被創(chuàng)建)。
app_namespace.dict中可以獲取到func_stack,
最后遍歷for handle in func_stack:
,并執(zhí)行handle, handle可能是Command實(shí)例對(duì)象,調(diào)用后,執(zhí)行call方法,執(zhí)行run方法,也可能是func函數(shù),直接被執(zhí)行。
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)
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
分享名稱:flask的flask_script和Manager的深入理解-創(chuàng)新互聯(lián)
本文URL:http://www.rwnh.cn/article6/csdhig.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、面包屑導(dǎo)航、微信小程序、電子商務(wù)、網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容