def get_local_test_settings_file(argv): assert argv[1] == "test" assert "manage.py" in argv[0] local_settings_dir = os.path.split(argv[0])[0] assert os.path.isfile(os.path.join(local_settings_dir, "manage.py")) from django.core.management.base import CommandParser parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--local_test_settings', dest="local_test_settings") try: options, args = parser.parse_known_args(argv) except CommandError: raise if options.local_test_settings is None: local_settings_file = "local_settings_example.py" else: local_settings_file = options.local_test_settings if os.path.split(local_settings_file)[0] == "": local_settings_file = os.path.join(local_settings_dir, local_settings_file) if os.path.abspath(local_settings_file) == os.path.abspath( os.path.join(local_settings_dir, "local_settings.py")): raise CommandError("Using production local_settings for tests is not " "allowed due to security reason.") if not os.path.isfile(local_settings_file): raise CommandError("file '%s' does not exist" % local_settings_file) return local_settings_file
def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. no_settings_commands = [ 'help', 'version', '--help', '--version', '-h', 'compilemessages', 'makemessages', 'startapp', 'startproject', ] try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc # A handful of built-in management commands work without settings. # Load the default settings -- where INSTALLED_APPS is empty. if subcommand in no_settings_commands: settings.configure() if settings.configured: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write(self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def run_from_argv(self, argv): try: super().run_from_argv(argv) except CommandError as e: parser = CommandParser() _, subcommand = parser.parse_known_args(argv[2:]) parser = self.create_parser(argv[0], argv[1]) for action in parser._actions: if action.dest is argparse.SUPPRESS: action.choices.get(subcommand[0]).print_help() except Exception as e: print(e)
def run_default_tests(command_line_args): # This reproduces the logic used by execute_from_command_line to # extra whether the subcommand is "test" and whether a settings # module has been manually specified. try: subcommand = command_line_args[1] except IndexError: return False parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') try: options, args = parser.parse_known_args(command_line_args[2:]) except CommandError: # Ignore any errors, we just wanted to extract any settings option # that might have been specified. options = {'settings': None} return subcommand == 'test' and not options.settings
def initialize(self): django.setup() parser = CommandParser(add_help=False, allow_abbrev=False) parser.add_argument('args', nargs='*') namespace, extra = parser.parse_known_args(self.argv[1:]) args = namespace.args if not args: args = ['help'] if '--debug' in extra: Runtime.debug(True) if '--no-color' in extra: Runtime.color(False) if not settings.NO_MIGRATE and args and args[0] not in ( 'check', 'migrate', 'makemigrations'): verbosity = 3 if Runtime.debug() else 0 start_time = time.time() current_time = start_time while (current_time - start_time) <= settings.AUTO_MIGRATE_TIMEOUT: try: call_command('migrate', interactive=False, verbosity=verbosity) break except Exception: pass time.sleep(settings.AUTO_MIGRATE_INTERVAL) current_time = time.time() return args
def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser('django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write(self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self, argv=None, stdout=None, stderr=None): if argv is None: argv = sys.argv if stdout is None: stdout = sys.stdout if stderr is None: stderr = sys.stderr if django.VERSION >= (1, 8): from django.core.management.base import CommandParser parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--version', action='store_true', help="show program's version number and exit") parser.add_argument('-h', '--help', action='store_true', help="show this help message and exit") try: options, argv = parser.parse_known_args(argv) except: pass # Ignore any option errors at this point. else: from django.core.management import LaxOptionParser parser = LaxOptionParser(usage="%prog subcommand [options] [args]", option_list=(), add_help_option=False) parser.add_option('--version', action='store_true', help="show program's version number and exit") parser.add_option('-h', '--help', action='store_true', help="show this help message and exit") try: options, argv = parser.parse_args(argv) except: pass # Ignore any option errors at this point. if len(argv) > 1: subcommand = argv[1] else: subcommand = 'help' # Display help if no arguments were given. if options.help: if subcommand == 'help': if hasattr(parser, 'print_lax_help'): parser.print_lax_help() else: parser.print_help(stdout) stdout.write(self.main_help_text() + '\n') else: command = self.fetch_command(subcommand) if command is not None: command.print_help(self.prog_name, subcommand, file=stdout) else: stdout.write(self.unknown_command_text(subcommand) + '\n') elif subcommand == 'version' or options.version: stdout.write(wirecloud.platform.__version__ + '\n') elif subcommand == 'help': if len(argv) <= 2: if hasattr(parser, 'print_lax_help'): parser.print_lax_help() else: parser.print_help(stdout) stdout.write(self.main_help_text() + '\n') elif argv[2] == '--commands': stdout.write(self.main_help_text(commands_only=True) + '\n') else: command = self.fetch_command(argv[2]) if command is not None: command.print_help(self.prog_name, argv[2], file=stdout) else: stdout.write(self.unknown_command_text(argv[2]) + '\n') else: command = self.fetch_command(subcommand) if command is not None: command.run_from_argv(argv, stdout=stdout, stderr=stderr) else: stdout.write(self.unknown_command_text(subcommand) + '\n')
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. 给出命令行参数,找出当前的子命令 运行, 创建一个适合该命令的解析器,然后运行它 """ try: subcommand = self.argv[1] # self.argv = sys.argv[:] # subcommand = "runserver" except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False) """ usage : 帮助 文档 add_help : 是否显示命令帮助 allow_abbrev: 可选参数 键 时候可以 简写 """ parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all # nargs : * 代表 可 连写 多个参数, 集合在一个列表中 try: options, args = parser.parse_known_args(self.argv[2:]) # options=== Namespace(args=['0.0.0.0:8888'], pythonpath=None, settings=None) # options : Namespace() , 所设定的 各选项 所对应的 值 # args : [] 除了 设定的 自定义选项, 在最后添加的 多余的 参数, handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: # 1.0 # 加载 默认全局的配置文件 global_settings.py 和 项目 自定义的 settings.py 文件 # 所有配置 都存储 在 settings._wrapped 属性中,值为 类实例 <class django.conf.Settings objects > settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc except ImportError as exc: self.settings_exception = exc # sys.argv == ['E:/DjangoProject/刘江/login-register-master/manage.py', 'runserver', '0.0.0.0:9999'] if settings.configured: # True, 代表 settings 配置 已 加载完毕 # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: # 2.0 autoreload.check_errors( django.setup)() # check_errors 为一个装饰器 except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. # 在所有其他情况下,需要 django.setup() 才能成功。 else: django.setup() # 配置设置 self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif not options.args: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv) # 提取命令
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. 1、命令行参数解析 2、 """ try: # 如果在调用django-admin 的时候没有给出任何的 命令 & 选项 # 那么slef.argv 列表只有一项 它就是slef.argv[0] 它的值为django-admin # 所以这种情况下正好会报 IndexError subcommand = self.argv[1] except IndexError: # 如果没有给出任何命令的情况下 把subcommand设置为help # 也就是说不给出命令的情况下 就当做是看django-admin的帮助. subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. # django 在标准库的argparser上作出了一些自定义 # CommandParser 继承了argparser.ArgumentParser # CommandParser 位于 jango.core.management.base 这个包中. # usage & add_help 都是argparser.ArgumentParser.__init__中的参数 # CommandParser.__init__(self, cmd, **kwargs): 由这里可以看了cmd=None parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: # settings 是在django.conf包中LazySettings类的实例 # 这里有个问题,就是在LazySettings类的代码中没有找到INSTALLED_APPS 的定义 # settings.INSTALLED_APPS 像这样的语句又有什么意义呢?难道它这样干就单单是为了引发异常? settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. 给定命令行参数,找出正在执行的子命令 运行,创建一个适合该命令的解析器,然后运行它。 """ # 1、是否取到位置1的参数, 否则显示帮助信息 try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # 2、参数预处理 # Preprocess options to extract --settings and --pythonpath. 提取一些 settings pythonPath的配置 # These options could affect the commands that are available, so they # must be processed early. 这些选项可能会影响到可用的命令 必须尽早处理 parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all # 3、 try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. # 4、是否配置INSTALLED_APPS try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc # 5、判断是否已配置设置 if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. # 5.1 命令== runserver 并且 noreload 不在传入的参数里面 if subcommand == 'runserver' and '--noreload' not in self.argv: try: #5.1.1 检查django 项目的完整性 - 装饰器 autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. # 5.2 其他的命令说明django 已经被安装成功 else: django.setup() # 6、输出启动完成信息 self.autocomplete() # 7 判断命令,最终并执行 if subcommand == 'help': # 7.1 帮助 if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: # 7.2 django版本获得 sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): # 7.3 获取帮助主文件 sys.stdout.write(self.main_help_text() + '\n') else: # 7.3 直接执行命令 - 链式调用 self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. """ # 先找出二级指令,没有二级指令就打印帮助信息 try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # 预处理的选项,这些选项会和当前传递的选项有冲突,所以先解析出这些选项,这样用户传递的选项才不会被影响. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) # 这里是指定settings文件 parser.add_argument('--settings') # 这里是指定python路径 parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) # 修改环境settings和pythonpath handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: # django在启动时会创建settings = LazySettings() # 通过读取os.environ.get('DJANGO_SETTINGS_MODULE'),来初始化settings对象 # settings是一个lazy对象,使用self._wrapped保存Settings对象,当读取属性时,lazy对象会先进行_setup,然后会调用getattr(self._wrapped,key) # 当要读取INSTALLED_APPS时,会先进行_setup # 说白了就是LazySetting对象读取属性时,会真正初始化Settings对象,并赋值给LazySetting._wrapped=Settings() settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc if settings.configured: # 就是返回self._wrapped is not empty,当前是否已经初始化好了settings # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: # 执行django.setup,如果有错误那么 autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser('django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: # 执行django.setup django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write(self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help(self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: # 这里执行fetch_command('runserver').run_from_argv(['/Users/mering/Proje...manage.py', 'runserver', '--noreload', '--nothreading']) # runserver 对应的是django.contrib.staticfiles # 加载该class import_module('%s.management.commands.%s' % (app_name, name)) # import_module('django.contrib.staticfiles.management.commands.runserver') # 放回的fetch_command(subcommand)=django.contrib.staticfiles.management.commands.runserver.Command() # django.contrib.staticfiles.management.commands.runserver.Command继承自django.core.management.Command, # run_from_argv会调用django.core.management.Command.excute-->django.core.management.BaseCommand.excute # django.core.management.commands.runserver.Command.handle # django.core.management.commands.runserver.Command.run # django.core.management.commands.runserver.Command.inner_run # django.contrib.staticfiles.management.commands.runserver.Command.get_handler 获得wsgiapp # Debug模式下返回StaticFilesHandler # django.core.servers.run # def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer): # server_address = (addr, port) # if threading: # # 创建一个新类型继承自socketserver.ThreadingMixIn和WSGIServer # httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {}) # else: # httpd_cls = server_cls # httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6) # if threading: # # ThreadingMixIn.daemon_threads indicates how threads will behave on an # # abrupt shutdown; like quitting the server by the user or restarting # # by the auto-reloader. True means the server will not wait for thread # # termination before it quits. This will make auto-reloader faster # # and will prevent the need to kill the server manually if a thread # # isn't terminating correctly. # httpd.daemon_threads = True # httpd.set_app(wsgi_handler) # httpd.serve_forever() self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. 给定命令行参数后,找出正在运行的子命令,创建适合该命令的解析器,并运行它。 """ try: # 子命令,例如 runserver 、migrate subcommand = self.argv[1] except IndexError: subcommand = 'help' # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: # 此对象是 django.conf.__init__.LazySettings 类的实例 # 此对象的全部属性都来自应用对象的 settings.py 配置文件 settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc except ImportError as exc: self.settings_exception = exc if settings.configured: #print('【django.core.management.__init__.ManagementUtility.execute】subcommand:', subcommand) #print('【django.core.management.__init__.ManagementUtility.execute】self.argv:', self.argv) if subcommand == 'runserver' and '--noreload' not in self.argv: try: # 参数 django.setup 是定义在 django.__init__ 模块中的函数 # 而 check_errors 是作检测异常之用 # 这里会调用 django.setup 函数 # 将 settings.INSTALLED_APPS 列表中的应用程序放到 apps.app_configs 字典中 # apps 对象可以看做一个应用对象收集器 autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(dict) apps.app_configs = {} apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif not options.args: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: # 下面的 fetch_command 方法根据命令行参数找到对应的模块中的 Command 类的实例并返回 # 它通过一个字典来找,每个命令都是字典中的一个 key # 根据命令找到对应的 value ,它是一个包的字符串,再据此找到包下面的 management/commands 子目录 # 然后在这个子目录下面找到与命令同名的文件 # 以 python manage.py makemigrate 命令为例 # 这个方法就会返回 .../management/commands/makemigrate.py 文件中的 Command 类的实例 # 下面的 cmd 我们称之为「命令处理对象」,以 runserver 命令为例 # 此对象的父类是 django.contrib.staticfiles.management.commands.runserver.Command 类 # 后者的父类是 django.core.management.commands.runserver.Command 类 # 后者的父类是 django.core.management.base.BaseCommand 类 cmd = self.fetch_command(subcommand) # 不论终端命令是啥 # 下面这个方法都定义在 django.core.management.base.BaseCommand 父类中 # 参数 self.argv 是终端命令参数列表,等同于 sys.argv # 这个方法会调用「命令处理对象」自身的 handle 方法控制其它对象启动线程和创建套接字啥的 cmd.run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. !!! OVERRIDED !!! Adding new user defined command-line arguments. """ try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version', # 'django-admin --help' to work, for backwards compatibility and # !!! USER DEFINED !!! # 'django-admin --importdirs' to pre-populate directories database. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif subcommand == 'importdirs' or subcommand == '--importdirs': check = False continue_bool = False try: args.index("--check") check = True except ValueError: pass try: args.index("--continue") continue_bool = True except ValueError: pass populate_db(settings.ROOT_DIRECTORY, settings.THUMBNAILS_DIRECTORIES, check, continue_bool) elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
from __future__ import unicode_literals
def execute(self): """ Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. """ # 1 Subcommand: 子程序名, 默认为help, 见上面定义 try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. # 2 处理和解析参数 parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. MY(1.0, '解析后的参数:', '\n\toptions:', options, '\n\targs:', args) # 3 LazySetting对象, __getattr__/__setattr__方法,完成INSTALLED_APPS赋值 # 懒加载. try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc # django.setup() # 4.1 配置日志 # 4.2 加载自定义模块 # 4.3 加载model模块 if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. # a 重新导入所有配置信息 if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. # b 配置日志, 加载自定义模块, models模块, 使用Application else: django.setup() self.autocomplete() # 5 fetch_command, 返回不同的Command对象, 根据不同的参数运行不同的后台任务, # 5.1 调用各个 BaseCommand 子类的方法来完成对应的业务, 例如: # runserver.py.Command # flush.py.Command # and so on # 5.2 不同Command流程(handle相当于钩子): # run_from_argv, 进行参数解析和配置, 调用execute # execute, 设置环境变量,运行handle, 在父类实现大部分逻辑; # handle, 进入run, 由各个子类rewrite, (主要处理逻辑) # run_from_argv, 处理善后 if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) elif subcommand == 'version' or self.argv[1:] == ['--version']: # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: MY(1, '\n\tShell subcommand:', subcommand, ' Argv:', self.argv) # 执行一个django-admin命令, 当然也可以自定义该命令 # 该函数: django.core.management.base self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ TODO:[-] 20-02-12 由入口函数调用的 Given the command-line arguments, figure out which subcommand is being run, create a parser appropriate to that command, and run it. """ try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(usage='%(prog)s subcommand [options] [args]', add_help=False, allow_abbrev=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) # 设置系统参数添加至 os.environ handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc except ImportError as exc: self.settings_exception = exc if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(dict) apps.app_configs = {} apps.apps_ready = apps.models_ready = apps.ready = True # Remove options not compatible with the built-in runserver # (e.g. options for the contrib.staticfiles' runserver). # Changes here require manually testing as described in # #27522. _parser = self.fetch_command('runserver').create_parser( 'django', 'runserver') _options, _args = _parser.parse_known_args(self.argv[2:]) for _arg in _args: self.argv.remove(_arg) # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif not options.args: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self): """ Given the command-line arguments, this figures out which subcommand is being run, creates a parser appropriate to that command, and runs it. """ try: subcommand = self.argv[1] except IndexError: subcommand = 'help' # Display help if no arguments were given. # Preprocess options to extract --settings and --pythonpath. # These options could affect the commands that are available, so they # must be processed early. parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--settings') parser.add_argument('--pythonpath') parser.add_argument('args', nargs='*') # catch-all try: options, args = parser.parse_known_args(self.argv[2:]) handle_default_options(options) except CommandError: pass # Ignore any option errors at this point. no_settings_commands = [ 'help', 'version', '--help', '--version', '-h', 'compilemessages', 'makemessages', 'startapp', 'startproject', ] try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc # A handful of built-in management commands work without settings. # Load the default settings -- where INSTALLED_APPS is empty. if subcommand in no_settings_commands: settings.configure() if settings.configured: # Start the auto-reloading dev server even if the code is broken. # The hardcoded condition is a code smell but we can't rely on a # flag on the command class because we haven't located it yet. if subcommand == 'runserver' and '--noreload' not in self.argv: try: autoreload.check_errors(django.setup)() except Exception: # The exception will be raised later in the child process # started by the autoreloader. Pretend it didn't happen by # loading an empty list of applications. apps.all_models = defaultdict(OrderedDict) apps.app_configs = OrderedDict() apps.apps_ready = apps.models_ready = apps.ready = True # In all other cases, django.setup() is required to succeed. else: django.setup() self.autocomplete() if subcommand == 'help': if '--commands' in args: sys.stdout.write( self.main_help_text(commands_only=True) + '\n') elif len(options.args) < 1: sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(options.args[0]).print_help( self.prog_name, options.args[0]) # Special-cases: We want 'django-admin --version' and # 'django-admin --help' to work, for backwards compatibility. elif subcommand == 'version' or self.argv[1:] == ['--version']: sys.stdout.write(django.get_version() + '\n') elif self.argv[1:] in (['--help'], ['-h']): sys.stdout.write(self.main_help_text() + '\n') else: self.fetch_command(subcommand).run_from_argv(self.argv)
def execute(self, argv=None, stdout=None, stderr=None): from django.core.management.base import CommandParser if argv is None: argv = sys.argv if stdout is None: stdout = sys.stdout if stderr is None: stderr = sys.stderr parser = CommandParser(None, usage="%(prog)s subcommand [options] [args]", add_help=False) parser.add_argument('--version', action='store_true', help="show program's version number and exit") parser.add_argument('-h', '--help', action='store_true', help="show this help message and exit") try: options, argv = parser.parse_known_args(argv) except: pass # Ignore any option errors at this point. if len(argv) > 1: subcommand = argv[1] else: subcommand = 'help' # Display help if no arguments were given. if options.help: if subcommand == 'help': parser.print_help(stdout) stdout.write(self.main_help_text() + '\n') else: command = self.fetch_command(subcommand) if command is not None: command.print_help(self.prog_name, subcommand, file=stdout) else: stdout.write(self.unknown_command_text(subcommand) + '\n') elif subcommand == 'version' or options.version: stdout.write(wirecloud.platform.__version__ + '\n') elif subcommand == 'help': if len(argv) <= 2: parser.print_help(stdout) stdout.write(self.main_help_text() + '\n') elif argv[2] == '--commands': stdout.write(self.main_help_text(commands_only=True) + '\n') else: command = self.fetch_command(argv[2]) if command is not None: command.print_help(self.prog_name, argv[2], file=stdout) else: stdout.write(self.unknown_command_text(argv[2]) + '\n') else: command = self.fetch_command(subcommand) if command is not None: command.run_from_argv(argv, stdout=stdout, stderr=stderr) else: stdout.write(self.unknown_command_text(subcommand) + '\n')