您的位置:首页 > 编程语言 > Go语言

django1.8源码分析 -- WSGI是如何启动的

2020-06-06 07:15 405 查看

1. django1.8源码分析 -- WSGI是如何启动的

我们都知道django提供一个WSGI服务器用于开发调试。那么django是如何启动的一个WSGI服务器呢?

入口:

python manage.py runserver

整个django的WSGI服务器就只有这一条语句:

utility.execute()

让我们看一下这个方法都做了什么。

1.1. 解析settings.py

try:
settings.INSTALLED_APPS #这里实际上真正想执行的是LazySettings中的_setup
except ImproperlyConfigured as exc:
# 如果django没有设置
# ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
# 会触发异常跳到这里
self.settings_exception = exc
# A handful of built-in management commands work without settings.
# Load the default settings -- where INSTALLED_APPS is empty.
if subcommand in no_settings_commands:
settings.configure() # configure也处理了settings.py这里应该是django留了一个钩子给用户定制的

首先需要看一下LazySettings(),用于读取settings.py,通过:

self._wrapped = Settings(settings_module)

self._wrapped就成了settings.py的包装。之后查询settings中的配置,只能从self._wrapped去查询了。

1.2. 导入app和app中的models.py

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

# In all other cases, django.setup() is required to succeed.
else:
django.setup()

这里,只有最后一句有用django.setup(),看看都做了什么。配置log子系统,没什么好讲的。 主要是这个,apps.populate(settings.INSTALLED_APPS) django的注释是这么说的:

Loads application configurations and models.
This method imports each application module and then each model module.
It is thread safe and idempotent, but not reentrant.

做了这样几件事情: app_config = AppConfig.create(entry) # 生成了一个AppConfig实例
self.app_configs[app_config.label] = app_config # 将所有的app实例放到一个order_dict中维护。
app_config.import_models(all_models) # 导入models.py

<!-- 这里出现了两个类,Apps 和 AppConfig. -->

1.3. 真正干活了

if subcommand == 'help':
if '--commands' in args:
sys.stdout.write(self.main_help_text(commands_only=True) + '\n')
elif len(options.args) < 1:
sys.stdout.write(self.main_help_text() + '\n')
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() + '\n')
elif self.argv[1:] in (['--help'], ['-h']):
sys.stdout.write(self.main_help_text() + '\n')
else:
self.fetch_command(subcommand).run_from_argv(self.argv)

help,version之类都没什么用,看最后一个分支。

self.fetch_command(subcommand).run_from_argv(self.argv) 我们只关注为什么runserver之后,django启动了一个WSGI 服务器。所以subcommand == 'runserver'。 self.fetch_command(subcommand)做了一些搜索遍历操作,就不详细讲了,最后找到了这个: https://github.com/django/django/blob/1.8.18/django/contrib/staticfiles/management/commands/runserver.py#L7

这里面最注重要的是 self.execute(*args, **cmd_options) 后面的步骤略复杂。 最后调用的是:

def run(addr, port, wsgi_handler, ipv6=False, threading=False):
server_address = (addr, port)
if threading:
httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
else:
httpd_cls = WSGIServer
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
# ThreadingMixIn.daemon_threads indicates how threads will behave on an
# abrupt shutdown; like quitting the server by the user or restarting
# by the auto-reloader. True means the server will not wait for thread
# termination before it quits. This will make auto-reloader faster
# and will prevent the need to kill the server manually if a thread
# isn't terminating correctly.
httpd.daemon_threads = True
httpd.set_app(wsgi_handler)
httpd.serve_forever()

其中比较重要的两个对象分别是:

完!

转载于:https://my.oschina.net/chaleaoch/blog/1524886

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: