• Django如何启动源码分析


    Django如何启动源码分析

    启动

    我们启动Django是通过python manage.py runsever的命令

    解决

    这句话就是执行manage.py文件,并在命令行发送一个runsever字符串

    解析manage.py

    #!/usr/bin/env python
    import os
    import sys
    
    if __name__ == "__main__":
    	#os.environ.setdefault 方法可以修改系统环境变量,但是只能os.environ 只能影响到当前运行程序
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "zx2.settings")
        try:
        	#导入模块,其实这里不单单只是导入execute_from_command_line这个方法,更多的是检查Django的模块,配置是否有问题
            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:
            	#精准判断是不是django模块的问题
                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
        #sys.argv是从外部获取参数,最后执行下面这个方法
        execute_from_command_line(sys.argv)
    

    测试sys.argv

    发现两种启动获取的参数不一样,但是第二个参数一样

    命令行启动项目
    ['manage.py', 'runserver']
    
    pycharm 启动项目
    ['C:/Users/Administrator/Desktop/01python/django/zx1/manage.py', 'runserver', '127.0.0.1:8000']
    

    解析execute_from_command_line(sys.argv)

    项目启动入口

    def execute_from_command_line(argv=None):
        """
        管理应用程序的简单方法
        A simple method that runs a ManagementUtility.
        """
        utility = ManagementUtility(argv)
        utility.execute()
    

    ManagementUtility初始化代码

    class ManagementUtility(object):
        """
        封装django-admin 和 manage.py的公共逻辑代码
        Encapsulates the logic of the django-admin and manage.py utilities.
        """
        def __init__(self, argv=None):
        	#把argv给self对象
            self.argv = argv or sys.argv[:]
            #返回path最后的文件名。若path以/或结尾,那么就会返回空值,为zx1
            self.prog_name = os.path.basename(self.argv[0])
            self.settings_exception = None
    

    utility.execute()分析

        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:
            	#self.argv[1]值为runserver
                subcommand = self.argv[1]
            except IndexError:
                subcommand = 'help'  # Display help if no arguments were given.
    		#预处理选项以提取--settings和--pythonpath。
            # 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:
            	#self.argv[2:]值为'127.0.0.1:8000',可以推断出这部分可能和启动服务器有关,并且有默认的ip和端口号
                options, args = parser.parse_known_args(self.argv[2:])
                handle_default_options(options)
            except CommandError:
                pass  # Ignore any option errors at this point.
    
            try:
            #获取app配置信息
                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) + '
    ')
                elif len(options.args) < 1:
                    sys.stdout.write(self.main_help_text() + '
    ')
                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() + '
    ')
            elif self.argv[1:] in (['--help'], ['-h']):
                sys.stdout.write(self.main_help_text() + '
    ')
            else:
                self.fetch_command(subcommand).run_from_argv(self.argv)
    

    后续代码有点看的迷糊了,没有找到socket启动的部分,以后再来

  • 相关阅读:
    人类登月不可或缺 大型机半个世纪发展史
    宽带上网知识(如何进行上网流程配置,路由器上网配置)
    团队项目第二阶段——第二天
    用户体验评价之QQ浏览器
    团队项目第二阶段——第一天
    第十四周学习进度总结
    《梦断代码》阅读笔记02
    第十三周学习进度总结
    第一阶段意见评论
    第十二周学习进度总结
  • 原文地址:https://www.cnblogs.com/zx125/p/11745863.html
Copyright © 2020-2023  润新知