应用环境
- 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,若是有不对的地方,欢迎指出。谢谢。