django1.8源码分析 -- 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
<!-- 这里出现了两个类,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()
其中比较重要的两个对象分别是:
- class WSGIHandler(base.BaseHandler)这是WSGI的客户端。
- class BaseCommand(object):以及它的子类class Command(BaseCommand和class Command(BaseCommand,这是command的封装。
完!
转载于:https://my.oschina.net/chaleaoch/blog/1524886
- django1.8源码分析 -- WSGI是如何启动的
- django源码分析--01服务启动(wsgi)
- Heritrix1.14源码分析(5) 如何让Heritrix在Ecplise等IDE下编程启动
- nova-api源码分析(WSGI server的创建及启动)
- Giraph源码分析(四)—— Master 如何检查Worker启动成功
- Monkey源码分析2—Monkey代码如何被启动执行
- Heritrix源码分析(五) 如何让Heritrix在Ecplise等IDE下编程启动
- Django源码分析3:处理请求wsgi分析与视图View
- django 的请求处理部分----WSGIHandler 源码分析 django1.5.5
- django 1.8 官方文档翻译: 6-6-2 如何使用WSGI 部署
- django源码分析 -- django启动初始化过程分析
- Heritrix源码分析(五) 如何让Heritrix在Ecplise等IDE下编程启动
- Giraph源码分析(四)—— Master 如何检查Worker启动成功
- Django系列之启动入口源码分析
- 【OpenStack源码分析之四】WSGI与Nova API服务启动
- 如何使用WSGI部署Django(1.8)
- Heritrix1.14源码分析(5) 如何让Heritrix在Ecplise等IDE下编程启动
- S5P210-uboot源码分析-uboot如何启动内核
- Heritrix源码分析(五) 如何让Heritrix在Ecplise等IDE下编程启动(转)
- tacker源码分析(Pike版本)--启动与路由映射