tornado源码分析系列 [网络层 IOLoop类] 优秀系列文章可以看看

本文详细介绍了IOLoop类的核心功能和内部实现,包括构造函数、事件循环监听方式的选择、管道的创建与使用,以及如何在不同操作系统环境下实现事件循环的唤醒机制。此外,还解释了add_handler、instance等关键方法的作用,以及如何通过字典管理和回调函数来实现高效的数据处理流程。
Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

看看IOLoop的类组织结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|---IOLoop
        ---__init__(self, impl=None)
        ---instance(cls)
        ---initialized(cls)
        ---add_handler(self, fd, handler, events)
        ---update_handler(self, fd, events)
        ---remove_handler(self, fd)
        ---set_blocking_signal_threshold(self, seconds, action)
        ---set_blocking_log_threshold(self, seconds)
        ---log_stack(self, signal, frame)
        ---start(self)
        ---stop(self)
        ---running(self)
        ---add_timeout(self, deadline, callback)
        ---remove_timeout(self, timeout)
        ---add_callback(self, callback)
        ---_wake(self)
        ---_run_callback(self, callback)
        ---handle_callback_exception(self, callback)
        ---_read_waker(self, fd, events)
        ---_set_nonblocking(self, fd)
        ---_set_close_exec(self, fd)
---|

从上一章的Demo里面可以看到最重要的对外提供的方法有

0.instance() @classmethod

1.add_handler(...)

2.start()

类似于传统的事件驱动方式,这里的使用方式也很简单

 

从IOLoop类中看起:

先是自己定义了几个EPOLL的宏,就是EPOLL的事件类型

#epoll 的事件类型,类似于这里的宏定义
_EPOLLIN = 0x001
_EPOLLPRI = 0x002
_EPOLLOUT = 0x004
_EPOLLERR = 0x008
_EPOLLHUP = 0x010
_EPOLLRDHUP = 0x2000
_EPOLLONESHOT = (1 << 30)
_EPOLLET = (1 << 31)

# Our events map exactly to the epoll events
#将这几个事件类型重定义一番
NONE = 0
READ = _EPOLLIN
WRITE = _EPOLLOUT
ERROR = _EPOLLERR | _EPOLLHUP | _EPOLLRDHUP

常用的就是三种,READ,WRITE,ERROR

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ioloop的构造函数
    def __init__(self, impl=None):
        #选择异步事件循环监听方式,默认是epoll,后面的_impl都是指的是epoll
        self._impl = impl or _poll()
        #自省,查看 self._impl 中是否有 fileno
        #如果有,就关闭起exec性质
        if hasattr(self._impl, 'fileno'):
            self._set_close_exec(self._impl.fileno())
        # _set_close_exec 是一个类方法,下面有定义
    # 当 FD_CLOEXEC 设置了以后,exec() 函数执行的时候会自动关闭描述符
"""     def _set_close_exec(self, fd):
            flags = fcntl.fcntl(fd, fcntl.F_GETFD)
            fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)   """
        #handlers 是一个函数集字典
        self._handlers = {}
        self._events = {}
        #回调函数使用的是列表
        self._callbacks = []
        #用来记录链接超时
        self._timeouts = []
        self._running = False
        self._stopped = False
        self._blocking_signal_threshold = None
 
        # Create a pipe that we send bogus data to when we want to wake
        # the I/O loop when it is idle
        #判断是否是 NT 操作系统
        if os.name != 'nt':
            #创建一个管道 ,返回的为读写两端的文件描述符
            r, w = os.pipe()
            #设置为非阻塞
            self._set_nonblocking(r)
            self._set_nonblocking(w)
            
            self._set_close_exec(r)
            self._set_close_exec(w)
            #分别以读方式和写方式打开管道
            self._waker_reader = os.fdopen(r, "rb"0)
            self._waker_writer = os.fdopen(w, "wb"0)
        else:
            #如若不是 NT 系统,改用win32 支持的管道类型
            self._waker_reader = self._waker_writer = win32_support.Pipe()
            = self._waker_writer.reader_fd
        #将 管道的  read端与 函数 _read_waker  关联,事件类型为 READ
        #这里也是IO 多路复用的一种机制,将管道的描述符也添加进多路复用的IO 管理
        self.add_handler(r, self._read_waker, self.READ)

注意最后的几点,将管道描述符的读端也加入事件循环检查,并设置相应的回调函数,这样做的好处是以便事件循环阻塞而没有相应描述符出现,需要在最大timeout时间之前返回,就可以向这个管道发送一个字符,用来终止阻塞在监听阶段的事件循环监听函数。

看看waker是这样定义的:

1
2
3
4
5
def _wake(self):
    try:
        self._waker_writer.write("x")
    except IOError:
        pass

需要唤醒阻塞中的事件循环监听函数的时候,只需要向管道写入一个字符,就可以提前结束循环

instance就是简单的返回一个实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def instance(cls):
    """Returns a global IOLoop instance.
 
    Most single-threaded applications have a single, global IOLoop.
    Use this method instead of passing around IOLoop instances
    throughout your code.
 
    A common pattern for classes that depend on IOLoops is to use
    a default argument to enable programs with multiple IOLoops
    but not require the argument for simpler applications:
 
        class MyClass(object):
            def __init__(self, io_loop=None):
                self.io_loop = io_loop or IOLoop.instance()
    """
    if not hasattr(cls"_instance"):
        cls._instance = cls()
    return cls._instance

instance()是一个静态方法,代表此IOLoop是一个单实例方法,一个进程只有一个

在add_handler()里面

1
2
3
4
5
6
7
8
#将文件描述符发生相应的事件时的回调函数对应
def add_handler(self, fd, handler, events):
    """Registers the given handler to receive the given events for fd."""
    self._handlers[fd] = stack_context.wrap(handler)
    #在 epoll 中注册对应事件
    #epoll_ctl
    self._impl.register(fd, events | self.ERROR)
#更新相应的事件类型

可以看到,使用字典的方式,每一个fd就对应一个handler,下次事件循环返回的时候按照返回后的fd列表,依次调用相应的callback

|------

在tornado中,函数是通过stack_context.wrap()包装过,可以用来记录上下文

如果需要调用被包装过的函数,需要调用方法

_run_callback(self, callback)  

这个函数将包装过的callback作为参数出入,然后执行函数

1
2
3
4
5
6
7
def _run_callback(self, callback):
    try:
        callback()
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handle_callback_exception(callback)

当函数执行发生异常时,可以记录下函数执行状态  

-------|

_impl.register就是被封装过的epoll的epoll_ctl,参数是EPOLL_CTL_ADD

见同一个文件下的_EPoll类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class _EPoll(object):
    """An epoll-based event loop using our C module for Python 2.5 systems"""
    _EPOLL_CTL_ADD = 1
    _EPOLL_CTL_DEL = 2
    _EPOLL_CTL_MOD = 3
 
    def __init__(self):
        self._epoll_fd = epoll.epoll_create()
 
    def fileno(self):
        return self._epoll_fd
 
    def register(self, fd, events):
        epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_ADD, fd, events)
 
    def modify(self, fd, events):
        epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_MOD, fd, events)
 
    def unregister(self, fd):
        epoll.epoll_ctl(self._epoll_fd, self._EPOLL_CTL_DEL, fd, 0)
 
    def poll(self, timeout):
        return epoll.epoll_wait(self._epoll_fd, int(timeout * 1000))

  

总结:这一章讲了IOLoop中的几个重要函数,后面依次会有分析其他方法,还有其中一些细节值得平常注意的。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

内容概要:本文详细介绍了“电动汽车聚合可行域的内-外结合近似方法”的Matlab代码实现,旨在通过数值仿真手段对大规模电动汽车集群作为灵活资源参与电网调度的能力边界进行建模与逼近。该方法融合内部凸包构造与外部约束逼近策略,精确刻画电动汽车在充电状态、功率调节、时间维度等方面的聚合可调能力范围,形成紧致的可行域表示,为高比例电动车接入下的电力系统优化调度、需求响应、车网互动(V2G)等关键应用提供可靠的建模基础。文中强调科研应兼顾严谨逻辑与创新思维,并倡导借助YALMIP等成熟优化工具提升研究效率。完整的代码、工具包及相关案例可通过指定网盘链接和微信公众号“荔枝科研社”获取。; 适合人群:具备电力系统分析、优化理论基础及Matlab编程能力的科研人员,尤其适用于从事新能源并网、电动汽车调度、智能电网、综合能源系统等方向的研究生与工程技术人员。; 使用场景及目标:①研究大规模电动汽车集群的聚合建模与灵活性量化方法;②实现电动汽车聚合可行域的内-外近似算法;③支撑含高渗透率电动汽车的电力系统日前-实时协同优化调度;④学习并应用YALMIP工具进行数学规划建模与求解;⑤为需求响应、市场机制设计及V2G运营提供技术支撑。; 阅读建议:建议读者按照文档指引循序渐进学习,结合网盘提供的完整资源(包括YALMIP工具包与示例代码)进行实践调试,重点掌握内-外近似方法的数学建模逻辑、约束处理技巧及优化求解流程,并参考团队发布的其他相关案例,深化对优化算法与仿真技术在能源系统中应用的理解。
下载代码方式:https://pan.quark.cn/s/93e47adaae45 医学研究人员近期识别了若干新型病毒,经由对这些病毒的解析,揭示出它们的遗传物质序列均呈现环状形态。当前,研究人员已汇集了丰沛的病毒遗传物质与人遗传物质样本数据,期望能迅速辨识个体是否感染了相关病毒。为便于探究,研究人员将人遗传物质与病毒遗传物质均表述为由若干字母构成的字符串序列。继而,检测某种病毒遗传物质序列是否在患者遗传物质序列中有所显现,倘若出现,则表明该个体感染了对应病毒,反之则未感染。《病毒感染检测实验报告》是在医学研究背景下,依托软件技术基础中的编程知识完成的一个课程设计任务,其目的在于评估人体是否感染特定病毒。在此实验中,病毒遗传物质与人遗传物质被表现为字母序列,通过比对病毒遗传物质序列是否存在于人的遗传物质序列中,从而判定感染状态。在程序构建方面,该实验所涉及的核心知识要点包括: 1. **字符串操作**:程序需处理病毒遗传物质与人遗传物质的序列,这些序列以字符串形式呈现。字符串操作涵盖输入、输出、比较及匹配等操作,是C/C++编程的基础。 2. **线性表**:遗传物质序列可视为线性数据结构,可通过数组来表示。程序运用全局变量数组`V`和`D`存储病毒与人的遗传物质序列。 3. **栈**:在循环展开病毒遗传物质时,可能需借助栈数据结构来保存某个阶段遗传物质序列的状态,以便进行所有可能的匹配尝试。 4. **BF算法**(Brute Force,暴力搜索算法):BF算法是一种基础性的字符串匹配方法,用于在文本中搜寻模式。在此,BF算法用于在人的遗传物质序列中探寻病毒遗传物质序列的所有展开形态。 5. **文件处理**:程序需从文件《病毒感染检测输入数据...
内容概要:本文系统研究了基于粒子群PSO、灰狼GWO、鲸鱼WOA、哈里斯鹰HHO、蜣螂DBO、麻雀SSA六种智能优化算法的无人机三维路径规划方法,并通过Matlab代码实现了在复杂三维环境下的路径搜索与优化对比。研究构建了包含障碍物、威胁区域等实际地形特征的空间模型,综合考虑路径长度、飞行时间、能耗及安全性等多维度成本函数,对各算法的寻优能力、收敛速度、稳定性和全局搜索性能进行了量化评估与深入分析。通过大量仿真实验,全面比较了不同算法在多样化环境条件下的路径规划表现差异,揭示了各算法的优势与局限性,为无人机在实际任务中的自主导航与决策提供了可靠的算法选型依据和技术支撑。; 适合人群:具备一定Matlab编程基础,从事无人机路径规划、智能优化算法研究或相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:① 掌握主流群智能优化算法在三维路径规划中的建模与实现方法;② 对比分析不同算法在复杂环境下的性能优劣,服务于算法选型与改进;③ 为无人机自主导航、无人系统协同控制等应用场景提供算法验证平台。; 阅读建议:此资源以Matlab代码为核心,建议读者结合代码与算法原理进行同步学习,通过调整环境参数与成本函数权重开展仿真实验,深入理解算法行为特征,并可根据自身研究需求进行二次开发与拓展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值