• Django(三)runserver 命令源码分析


    应用环境

    • windows7
    • pycharm2018 profession
    • python3.6
    • django2.0

    我们在pycharm 启动django项目时,常常有这么一个命令操作:

    • python manage.py runserver

     这里的意思是执行python命令,传入的参数为 manage.py runserver。这两个参数就会被保存到sys.argv 列表中。如下,新建一个demo.py

    import sys
    
    
    print('hello sys.argv')
    print(type(sys.argv))
    for arg in sys.argv:
        print(arg)

    在terminal窗口执行 python demo.py runserver  #  循环遍历sys.argv 输出参数

    PS:这里解释sys.argv 是因为在manage.py中,会用到。

    打开我们的manage.py文件,可以看到,这里调用的是:

    • execute_from_command_line(sys.argv)

    可以看到这里传入的就是我们执行python 命令传入的参数(这里是manage.py runserver)。

    我们进入到 execute_from_command_line 函数,可以看到的是执行

    • utility.execute()

    在execute这个函数中有这么一行代码,读取子命令,也即是读取sys.argv列表中第二个元素runserver,如下图

    同时,在execute函数中,我们需要重点关注的是最后这一行代码:

    • self.fetch_command(subcommand).run_from_argv(self.argv)

    这里传入的上面的读取的子命令sys.argv[1] 以及self.argv(这里的self.argv 是在构造函数中传入的sys.argv)。

    我们进入到 fetch_command 函数,这里最后返回的一个Command class instance 。也就是说 

    • self.fetch_command(subcommand).run_from_argv(self.argv) 

    这行代码的意思是 执行返回的实体类必然包含 run_from_argv函数。

    在fetch_command中,最终调用的是

    • import_module('%s.management.commands.%s' % (app_name, name))

    这里的注释:

    Given a command name and an application name, return the Command
    class instance.

    通过名字返回实例,这里类似net中IL编程:动态导入(动态生成程序集)【这是本篇博文的重点】。
    通过:
    print('%s.management.commands.%s' % (app_name, name))
    我们发现动态导入的实例是:
    • django.contrib.staticfiles.management.commands.runserver

    而我们的 import_module 函数最终执行的也是python标准库 importlib下importlib._bootstrap中的gcd_import。如图:

    通过上面的分析,我们知道最终执行的是模块:

    • django.contrib.staticfiles.management.commands.runserver

    下的run_from_argv 函数。

    我们打开runserver.py文件,也确是没有找到该函数,而在其父类中找到:

    从上图看出,这个函数最终执行的是execute函数。而在execute中最终执行却又是:

    • output = self.handle(*args, **options)

    这里的handle是:

        def handle(self, *args, **options):
            """
            The actual logic of the command. Subclasses must implement
            this method.
            """
            raise NotImplementedError('subclasses of BaseCommand must provide a handle() method')

    我们从注释可以知道,这个方法需要由子类实现的,也即最后,最后,最后执行的runserver中handle函数。

    分析到这里,已基本很明了,最终执行的是在本地的8000端口启动一个socketserver监听程序。

    分析所得:

    • get到python如何进行动态的导入
    • sys.argv 存储了全局中输入参数
    • sys.moduls注册了程序运行已经导入模块
    • if 赋值的优雅写法 subcommand = 'runserver'  if 1== 'condition' else 'hello'

    这里一行代码等价于这么写:

    if 1=='condition' :

        subcommand = 'runserver'

    else:

      subcommand = 'hello'

    这里一行代码搞定,看起来不错。

    希望这篇文字可以帮助到大家。刚接触python,若是有不对的地方,欢迎指出。谢谢。 

  • 相关阅读:
    英语apyrite红碧玺apyrite单词
    英语SouthRedAgate南红玛瑙
    英语kutnahorite金田黄kutnahorite单词
    英语chalchite蓝绿松石chalchite单词
    单词demantoite翠榴石demantoite英语
    英语fieldyellowstone田黄石fieldyellowstone单词
    Http通讯Util
    redis分布式锁工具类
    永不重复的id生成器
    二维码生成工具类
  • 原文地址:https://www.cnblogs.com/liangxiarong/p/8721816.html
Copyright © 2020-2023  润新知