django-1.8-源码阅读笔记 -- django自带的wsgi服务器是如何启动的

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

 

 

 

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://www.cnblogs.com/chaleaoch/p/7299178.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值