hello,各位好,好久没有更新,一直在整理Tornado 底层源码,力求用最少的代码来为大家讲解清楚其底层的运行原理。看到标题是否想到今天会分享什么呢? 先从一张图中看一下tornado 各个部件 的位置:
不知大家是否记得上次我们讲过的代码,其中一个片段是这样的: tornado.ioloop.IOLoop.instance().start() 我们今天就从这句开始分析,从图上我们也能看到 IOLoop是最底层的,这个是做什么的呢?这个是一个“大循环”,是事件循环的核心代码。单击进入我们先大概看一下长什么样子的:
从图片可以看出,这个IOLoop类是继承了 Configurable 这个类。为何要继承这个类?能为IOLoop做什么呢? 我们看一下代码:[注意:我贴出的代码是我删减过后的代码,只为给大家说清楚其主要逻辑和设计思路] 先整体看一下涉及到的主要函数内容:
代码语言:javascript复制# -*- encoding: utf-8 -*-
# !/usr/bin/python
"""
@File : configure_core.py
@Time : 2020/5/23 18:10
@Author : haishiniu
@Software: PyCharm
"""
from tornado.util import unicode_type, import_object
class Configurable(object):
__impl_class = None # type: type
__impl_kwargs = None # type: Dict[str, Any]
def __new__(cls, *args, **kwargs):
base = cls.configurable_base() # 返回子类的配置基类 -->IOLoop
init_kwargs = {}
# 如果子类的配置基类就是子类本身,那么:
# 如果配置基类通过__impl_class 属性指定了实现类,则使用它;
# 否则,使用子类的 configurable_default() 方法返回的实现类。
if cls is base:
impl = cls.configured_class() # 具体实现类[底层的IO多路复用机制]EPollIOLoop
if base.__impl_kwargs:
init_kwargs.update(base.__impl_kwargs)
# 如果子类的配置基类不是自身,直接使用子类作为实现类。
else:
impl = cls
init_kwargs.update(kwargs)
# 创建实现类的实例
instance = super(Configurable, cls).__new__(impl)
# 使用传递给构造方法的参数,调用实例的initialize方法,进行初始化。
# 实例的__init__方法也会被自动调用,但是一般不应该使用__init__方法进行初始化,而是建议使用initialize方法
instance.initialize(*args, **init_kwargs) # EPollIOLoop(initialize) --> PollIOLoop(initialize) --> IOLoop --> Configurable
return instance
# configurable_base() 方法用于 返回子类的配置基类。通常,子类的配置基类就是其自身(但是不是必须)。
# issubclass(子类, 配置基类) == True。
# 该方法需要在子类中实现。
@classmethod
def configurable_base(cls):
# type: () -> Any
raise NotImplementedError()
# configured_class()方法的作用是:
# 如果子类的__impl_class属性是None(也就是,其配置基类没有通过__impl_class属性指定实现类),
# 那么,则使用它的 configurable_default() 方法返回的类作为实现类,并将其保存到配置基类的__impl_class属性中;
# 否则,直接使用配置基类的__impl_class属性指定的实现类。
# 实现类是子类自身或其子类。
@classmethod
def configured_class(cls):
# type: () -> type
base = cls.configurable_base() # 返回子类的配置基类 -->IOLoop
if cls.__impl_class is None:
base.__impl_class = cls.configurable_default() # 具体实现类[底层的IO多路复用机制]EPollIOLoop
return base.__impl_class
# configure()方法用于在 运行时,为 Configurable的子类指定实现类,以及初始化时使用的参数。
# 它们会被保存到 子类的配置基类的 __impl_class 和 __impl_kwargs属性中
@classmethod
def configure(cls, impl, **kwargs):
# type: (Any, **Any) -> None
base = cls.configurable_base() # 返回子类的配置基类 -->IOLoop
if isinstance(impl, (str, unicode_type)):
impl = import_object(impl)
if impl is not None and not issubclass(impl, cls):
raise ValueError("Invalid subclass of %s" % cls)
base.__impl_class = impl
base.__impl_kwargs = kwargs
# 简单总结:
# 继承 Configurable 的子类,需要实现下列的方法:
# 1.configurable_base(cls):通常返回子类自身
# 2.configurable_default(cls):返回默认的实现类,比如根据不同的操作系统平台,返回不同的实现类
# 子类的实现类,需要实现:
# initialize(self, *a, **kw):用于实例的初始化
# Configurable的核心是其构造方法:__new__。它是 其实现子类的 [工厂方法]。
# 在新式类中,如果子类没有定义__new__方法,那么会使用父类的该方法,来创建对象。
# 因此,Configurable的 未定义__new__方法的子类(比如IOLoop等) 都会使用Configurable的[构造方法]。