Django源码解析(1):启动程序
1、Django的启动
1.1、启动命令
在Django项目根目录执行启动命令,如下:
python manage.py runserver 8008
1.2、执行manage.py
manage.py源码:
if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "middleware_demo.settings") try: from django.core.management import execute_from_command_line except ImportError: # The above import may fail for some other reason. Ensure that the # issue is really that Django is missing to avoid masking other # exceptions on Python 2. try: import django except ImportError: raise ImportError( "Couldn't import Django. Are you sure it's installed and " "available on your PYTHONPATH environment variable? Did you " "forget to activate a virtual environment?" ) raise execute_from_command_line(sys.argv)
解析:
- 首先设置系统环境变量
- 从django.core.management模块中导入execute_from_command_line()函数,用于执行从终端输入的命令,如"python manage.py runserver 8008"。
- 如果上一步发生导入错误(ImportError),则尝试导入django,如果发生导入错误(ImportError),抛出一个ImportError错误,说明不能正常导入Django,让你确认是否安装了Django并将其安装目录注册到环境变量中。
- 最后执行execute_from_command_line(sys.argv)来执行从终端CMD输入的命令
1.3、execute_from_command_line的执行
1.3.1、源码
def execute_from_command_line(argv=None): """Run a ManagementUtility.""" utility = ManagementUtility(argv) utility.execute()
1.3.2、解析
- 实例化类ManagementUtility
utility = ManagementUtility(argv)
将参数argv传入类ManagementUtility进行实例化,将self.prog_name赋值为'manage.py'。
- 执行实例化对象的execute()方法
utility.execute()
1.4、utility.execute()的执行
1.4.1、源码
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) 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)
1.4.2、解析