首页 > 解决方案 > 执行“python manage.py runserver”命令后会发生什么?

问题描述

我很想知道执行“python manage.py runserver”命令时发生的所有步骤。

标签: django

解决方案


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()

正如我们可以清楚地看到它从导入execute_from_command_line方法django.core.management,然后使用sys.argv作为参数调用函数。该参数sys.argv是一个列表,其中包含目录位置、执行的命令(runserver在我们的例子中)和托管开发服务器的 IP 地址等值。当我们进入该函数时,我们看到我们ManagementUtitlity通过将参数传递给它的构造函数来创建一个实例。

def execute_from_command_line(argv=None):
    """Run a ManagementUtility."""
    utility = ManagementUtility(argv)
    utility.execute()

构造函数接受程序名称和其他参数,但这些东西现在对我们来说并不重要。返回实例并instance.execute调用方法。

在执行函数中,子命令形式获得了完整的命令,在我们的例子中是runserver. 如果没有给出命令,则使用错误处理机制将子命令作为帮助。在这里,我们实例化一个名为的类CommandParser,它扩展了ArgumentParser内置库中的一个类argparse。对于不知道是什么的人来说argpase,它是 python 库,用于构建用户友好的命令行工具。

对于这个命令解析器,解析两个参数:一个是用法,其值设置为%(prog)s subcommand [options] [args],另一个add_help是设置为 false。当我们进入它时,我们会看到一个cmd已初始化的变量,并且剩余的关键字参数被发送到超类构造函数。踏入其中,会发生很多事情。初始化各种实例变量,并再次使用 4 个参数调用超类构造函数:description(none)prefix_chars(‘-’)argument_default(None)conflict_handler(error)。我们不会讨论这个,因为这是内置模块的实现argparse在这个模块中发生的所有事情旁边。尽管他们使用正则表达式来查找选项是否看起来像负数,但有一件事引起了我的注意。返回解析器对象并将参数添加到解析器。现在检查该runserver命令是否使用标志调用— noreload,如果没有,则有一行有趣的代码:

autoreload.check_errors(django.setup)()

autoreload又是 django 的 utils 中的一个不同模块,因为名称本身表明它具有与自动重新加载功能相关的所有功能django. autoreloade.check_errors。它是一个装饰器,它接收一个函数并返回一个包装函数,该函数具有异常处理机制,当异常发生时,它扮演着显示文件名的角色。它接受django.setup函数并将其包装并返回。返回时调用该函数。进去的时候是这个样子的。

因此,正如首先显示的那样,根据我的配置,这是我们在与开发服务器进行任何交互时看到的所有日志消息的原因。该configure_logging函数首先查找并导入日志记录配置,然后使用设置调用它。现在apps.populate方法settings.INSTALLED_APPS作为参数被调用。对于那些不记得settings.INSTALLED_APPS的是 settings.py 文件中的列表,您可以在其中注册所有应用程序。该apps.populate方法导入所有应用程序配置和这些应用程序配置中的所有模型模块。这是一个线程安全的方法,RLOCK因为这个方法可以被服务器上运行的两个或多个线程调用,并且RLOCK防止其他线程重新进入这个方法。populate 方法分为三个阶段:

第 1 阶段:初始化应用程序配置并导入应用程序模块。在此之后它检查任何重复的应用程序名称,如果发现显示improperly configured错误

Phase-2:导入这些应用程序的模型模块。

Phase-3:运行每个应用配置的就绪功能

完成所有这些后,控件返回到 setup 函数,然后返回到ManagementUtil. 有一个异常处理机制,如果由 autoreloader 启动的进程引发的异常再次重新启动服务器。如果 runserver 命令带有— noreload标志,那么这一切都会被跳过,只django.setup调用函数。

现在,self.autocomplete调用了一个方法。这是一个通过使用空格分隔的字符串来建议 bash 命令的功能,当用户没有源文件时这不起作用bash_completion(在环境变量中检查,它有DJANGO_AUTO_COMPLETE)。毕竟,它具有针对不同子命令的条件语句。如果help然后打印有关帮助的信息,如果version有关版本的详细信息,则执行以下代码:

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

fetch_command函数采用子命令,在我们的例子中是runserver,并使用get_command方法填充命令字典,该方法返回命令名称和回调应用程序的字典。如果由于未配置的设置文件而缺少子命令,则会打印错误。如果命令类先前已加载,则使用它,否则已加载并返回子命令类。现在run_from_argv该类的方法self.argv作为参数调用。所有命令类都是从一个类扩展而来的BaseCommand,并且功能run_from_argv在该类中实现。

当我们介入时,我们argv在索引 1 和 2 处创建一个带有参数的解析器对象,它们是文件位置和命令。这在内部解析已知参数并返回解析的参数。我们还得到了一些选项,cmd_options现在我们self.execute以 args 和选项作为参数调用方法。这将执行 django 的executefromrunserver类。这是运行时多态性的一个例子。这会进行一些检查并调用超类的(即BaseCommandexecute方法。这将执行命令并在需要时执行基本检查。如果需要,这将执行正常检查和迁移检查,然后调用一个名为handle. 此功能对 IP 地址进行所有检查,例如检查端口、IP 地址格式 ipv4 或 ipv6。如果未指定地址,则默认地址为address(即 localhost)。

现在这调用了一个run函数。在run函数中,如果use_reloader选项为真,则它调用inner_functionelse 将inner_functionass 参数传递给autoreload.main. 在这种情况下,传递的函数用check_error装饰器包装,并且包装的函数作为参数传递给python_reloader模块autoreload。这将在不同的线程上运行与该命令相关的函数。该功能负责服务器的工作。在此之后,它调用一个名为 的方法reloader_thread()。顾名思义,这个函数负责重新加载机制。

介入后,reloader_thread调用了一个ensure_echo_on什么都不做的方法。现在,如果一个常数USE_INOTIFY为真,那么变化检测函数就是inotify_code_changedcode changed。对我来说,代码检测功能是code_changed. 出于好奇,我搜索了一些关于我通知的内容,发现 Inotify(inode notify)是一个 Linux 内核子系统,用于扩展文件系统以通知文件系统的更改,并将这些更改报告给应用程序。

我认为由于我的笔记本电脑是 windows,我无法使用inotify. 因此,在 windows 使用某些时间戳检测文件更改的功能中。它存储所有修改后的时间戳,并且每当注意到任何更改时,I18N_MODIFIED如果更改的文件以.mo(二进制文件的扩展名)结尾,则返回值 = 2,否则返回FILE_MODIFIED值 = 1。如果未检测到更改,则返回 false。如果返回值是FILE_MODIFIED,则程序被强制重新加载,如果返回值是I18N_MODIFIED,则reset_translation调用方法。这个循环结束时有 1 秒的睡眠时间。所以这个检查每秒钟发生一次,因此当对文件进行任何更改时,django 开发服务器会自动重新加载。

这就是执行命令时发生的所有事情python manage.py runserver。这可能是一个漫长的过程,但值得了解。下一次,当您点击命令时,您将对正在发生的事情有更高层次的了解。


推荐阅读