我很想知道在执行“ python manage.py runserver”命令时所有步骤会发生什么。
答案 0 :(得分:0)
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'slambook.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
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?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
我们可以清楚地看到它从django.core.management导入execute_from_command_line方法,然后使用“ sys.argv”作为参数调用该函数。 sys.argv是一个列表,其中包含诸如目录位置,执行的命令(在本例中为runserver)以及托管开发服务器的IP地址之类的值。当我们进入该函数时,我们看到我们通过将参数传递给其构造函数来创建“ ManagementUtitlity”的实例。
def execute_from_command_line(argv=None):
"""Run a ManagementUtility."""
utility = ManagementUtility(argv)
utility.execute()
构造函数带有程序名和其他参数,但是这些东西对我们来说现在并不重要。返回实例并调用instance.execute方法。
在execute函数中,从完成命令获得子命令,在我们的例子中是runserver。如果未给出命令,则它将使用错误处理机制将子命令作为帮助。在这里,我们实例化了一个名为CommandParser的类,该类从内置库argparse扩展了ArgumentParser类。对于不知道argpase是什么的人来说,它是python库,用于构建用户友好的命令行工具。 对于此命令解析器,将解析两个参数,一个是用法,其值设置为“%(prog)s子命令[options] [args]”,另一个是add_help,该参数设置为false。当我们进入其中时,我们会看到一个变量cmd,该变量已初始化,剩余的关键字参数发送到超类构造函数。进入它会发生很多事情,各种实例变量被初始化,并且再次使用4个参数description(none),prefix_chars('-'),argument_default(None),冲突_handler(“ error”)调用超类构造函数。我们不做这件事,因为这是内置模块argparse的实现,除了该模块中发生的所有事情外,一件事情引起了我的注意,他们使用正则表达式查找是否有负数来查看是否有一个选项看起来像一个负数。返回解析器对象,并将参数添加到解析器。现在检查一下,是否用标志“ — noreload”调用了runserver命令,如果没有,则有一行有趣的代码 “ autoreload.check_errors(django.setup)()” autoreload还是django的utils中的另一个模块,因为名称本身表明它具有与django的自动重载功能相关的所有功能。 autoreloade.check_errors是一个装饰器,它接受一个函数并返回一个包装的函数,该函数具有异常处理机制,该机制在发生异常时起着显示文件名的作用。它使用django.setup函数并将其包装并返回。返回时将调用该函数。踏入时看起来像这样
因此,首先显示配置了日志记录,这是我与开发服务器进行任何交互时看到的所有日志记录消息的原因。 configure_logging函数首先查找并导入日志记录配置,然后使用设置调用它。现在,使用settings.INSTALLED_APPS作为参数调用apps.populate方法。对于那些不记得设置的用户。INSTALLED_APPS是settings.py文件中的列表,您可以在其中注册所有应用。 apps.populate方法导入所有应用程序配置和这些应用程序配置中的所有模型模块。这是带有RLOCK的线程安全方法,因为该方法可以由服务器上运行的两个或多个线程调用,并且RLock阻止其他线程重新进入此方法。填充方法分为三个阶段。 阶段-1:初始化应用程序配置并导入应用程序模块。在此之后,它检查是否有重复的应用程序名称,如果找到则显示“配置不正确”错误 阶段-2:这些应用程序的导入模型模块。 阶段-3:运行每个应用程序配置的ready功能 完成所有这些操作后,控件将返回到设置功能,然后返回到ManagementUtil的执行功能。有一个异常处理机制,用于自动重新加载程序启动的进程引发的异常,以重新启动服务器。如果运行服务器命令使用“ — noreload”标志执行,则将全部跳过,仅调用django.setup函数。现在调用了self.autocomplete方法。此功能是通过使用空格分隔的字符串来建议bash命令的功能,当用户未获取bash_completion文件(在环境变量中进行了检查,它具有“ DJANGO_AUTO_COMPLETE”)时,该功能不起作用。毕竟,它具有用于不同子命令的条件语句。如果为“ help”,则打印有关帮助的信息,如果为“ version”,则打印有关版本的详细信息,否则它将执行以下代码 self.fetch_command(子命令).run_from_argv(self.argv) fetch_command函数采用子命令,在本例中为runserver,并使用get_command方法填充命令字典,该方法返回命令名称的字典并在其中回调应用程序。如果由于未正确配置的设置文件而丢失了子命令,则会打印错误。如果命令类是先前加载的,则使用它,否则将其加载,并返回子命令类。现在,以self.argv作为参数调用该类的“ run_from_argv”方法。所有命令类都从BaseCommand类扩展而来,并且在该类中实现了函数“ run_from_argv”。 当我们进入时,我们使用argv中位于索引1和2的参数创建一个解析器对象,它们是文件位置和命令。这在内部解析已知参数并返回解析后的参数。我们还获得了一些选项和cmd_options,现在我们以args和options为参数调用self.execute方法。这将从Django的runserver类执行execute。这是运行时多态的一个示例。这会进行一些检查,并调用超类(即BaseCommand)的execute方法。这将执行命令并在需要时执行基本检查。这将在需要时执行常规检查和迁移检查,然后调用一个称为handle的函数。此功能对IP地址进行所有检查,例如检查端口,IP地址格式ipv4或ipv6。如果未指定地址,则输入默认地址为address(即localhost)。 现在,这将调用运行函数。在run函数中,如果use_reloader选项为true(如果为false),则它调用inner_function,否则将inner_function ass参数传递给autoreload.main。在这种情况下,传递的函数用check_error装饰器包装,并且包装的函数作为参数传递给autoreload模块的python_reloader。这将在另一个线程上运行与该命令相关的功能。该功能负责服务器的工作。此后,它调用一个称为reloader_thread()的方法。顾名思义,此功能负责重新加载机制。
单步执行reloader_thread调用一个不执行任何操作的方法,确保方法为sure_echo_on。现在,如果常量“ USE_INOTIFY”为true,则更改检测功能为“ inotify_code_changed”,否则为“代码已更改”。对我来说,代码检测功能是“ code_changed”。出于好奇,我搜索了一些有关我所通知的内容并发现了 Inotify(inode通知)是一个Linux内核子系统,用于扩展文件系统以通知文件系统更改,并将这些更改报告给应用程序。 我认为由于笔记本电脑是Windows,所以无法使用inotify。因此,在Windows可以使用的功能中,使用一些时间戳来检测文件中的更改。它存储所有修改后的时间戳,并且每当注意到任何更改时,如果更改后的文件以“ .mo”(二进制文件的扩展名)结尾,则返回“ I18N_MODIFIED”值= 2,否则返回“ FILE_MODIFIED”值= 1。如果未检测到更改,则返回false。如果返回值为“ FILE_MODIFIED”,则将强制重新加载程序,如果返回值为“ I18N_MODIFIED”,则将调用reset_translation方法。最终,此循环的睡眠时间为1秒。因此,此检查每隔一秒钟发生一次,因此,对文件进行任何更改时,django开发服务器都会自动重新加载。 这就是执行命令“ python manage.py runserver”时发生的一切。这可能是一个漫长的过程,但却使人不解。下次单击该命令时,您将对发生的事情有更高的了解。