tornado.ioloop ---主事件循环

用于非阻塞套接字的I/O事件循环。

在 Tornado 6号, IOLoop 是一个包装 asyncio 事件循环,由于历史原因,接口略有不同。应用程序可以使用 IOLoop 接口或底层 asyncio 直接事件循环(除非需要与旧版Tornado兼容,在这种情况下 IOLoop 必须使用。

典型应用将使用一个 IOLoop 对象,通过访问 IOLoop.current 类方法。这个 IOLoop.start 方法(或同等方法, asyncio.AbstractEventLoop.run_forever )通常应在 main() 功能。非典型应用程序可以使用多个 IOLoop ,比如一 IOLoop 每个线程,或每个 unittest 案例。

IOOOP对象

class tornado.ioloop.IOLoop(*args: Any, **kwargs: Any)[源代码]

I/O事件循环。

从 Tornado 6.0开始, IOLoop 是一个包装 asyncio 事件循环。

简单TCP服务器的示例用法:

import asyncio
import errno
import functools
import socket

import tornado.ioloop
from tornado.iostream import IOStream

async def handle_connection(connection, address):
    stream = IOStream(connection)
    message = await stream.read_until_close()
    print("message from client:", message.decode().strip())

def connection_ready(sock, fd, events):
    while True:
        try:
            connection, address = sock.accept()
        except BlockingIOError:
            return
        connection.setblocking(0)
        io_loop = tornado.ioloop.IOLoop.current()
        io_loop.spawn_callback(handle_connection, connection, address)

async def main():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setblocking(0)
    sock.bind(("", 8888))
    sock.listen(128)

    io_loop = tornado.ioloop.IOLoop.current()
    callback = functools.partial(connection_ready, sock)
    io_loop.add_handler(sock.fileno(), callback, io_loop.READ)
    await asyncio.Event().wait()

if __name__ == "__main__":
    asyncio.run(main())

不要试图构造一个 IOLoop 直接;从Tornado 6.2开始就不再推荐使用该功能。相反,应初始化 asyncio 事件循环和使用 IOLoop.current() 要访问 IOLoop 包装当前事件循环。

一般来说,一个 IOLoop 不能在fork中生存,也不能以任何方式在进程间共享。当使用多个进程时,每个进程都应该创建自己的进程 IOLoop 也意味着任何依赖于 IOLoop (如 AsyncHTTPClient )还必须在子进程中创建。作为指导方针,启动流程的任何内容(包括 tornado.processmultiprocessing 模块)应该尽可能早地这样做,理想情况下,应用程序在加载其配置后要做的第一件事是 main() .

在 4.2 版更改: 增加了 make_current 关键字参数 IOLoop 建造师。

在 5.0 版更改: 使用 asyncio 默认情况下为事件循环。这个 IOLoop.configure 方法不能在python 3上使用,除非冗余地指定 asyncio 事件循环。

6.2 版后已移除: 不建议创建“当前”但当前未运行的事件循环。这意味着它不推荐使用 make_current=True 发送到 IOLoop 构造函数,或创建一个 IOLoop 而没有正在运行的异步事件循环,除非 make_current=False 是使用的。

运行IOLoop

static IOLoop.current() IOLoop[源代码]
static IOLoop.current(instance: bool = True) Optional[IOLoop]

返回当前线程的 IOLoop .

如果一个 IOLoop 当前正在运行或被标记为当前 make_current ,返回该实例。如果没有电流 IOLoopinstance 是真的,创造了一个。

在 4.1 版更改: 补充 instance 用于控制回退的参数 IOLoop.instance() .

在 5.0 版更改: 在python 3上,控制当前 IOLoop 委派给 asyncio ,使用此方法和其他方法作为传递访问器。这个 instance 参数现在控制 IOLoop 当没有时自动创建,而不是返回 IOLoop.instance() (现在是此方法的别名)。 instance=False 已弃用,因为即使我们不创建 IOLoop ,此方法可以初始化Asyncio循环。

6.2 版后已移除: 不推荐调用 IOLoop.current() 当没有 asyncio 事件循环正在运行。

IOLoop.make_current() None[源代码]

使这个 IOLoop 对于当前线程。

IOLoop 当线程启动时自动变为当前线程,但有时调用 make_current 在启动 IOLoop ,以便在启动时运行的代码可以找到正确的实例。

在 4.1 版更改: IOLoop 在没有当前数据时创建 IOLoop 将自动变为当前状态。

在 5.0 版更改: 此方法还设置当前 asyncio 事件循环。

6.2 版后已移除: 在从Python3.10开始的Asyncio中,不推荐使用“当前”而不是当前正在运行的事件循环的概念。Tornado中的所有相关功能也已弃用。相反,使用以下命令开始事件循环 asyncio.run 在与它互动之前。

static IOLoop.clear_current() None[源代码]

清除 IOLoop 对于当前线程。

主要供测试框架在测试之间使用。

在 5.0 版更改: 此方法还清除当前 asyncio 事件循环。

6.2 版后已移除.

IOLoop.start() None[源代码]

启动I/O循环。

循环将一直运行到其中一个回调调用 stop() ,这将使循环在当前事件迭代完成后停止。

IOLoop.stop() None[源代码]

停止I/O循环。

如果事件循环当前未运行,则下次调用 start() 将立即返回。

注意,即使在 stop 被称为 IOLoop 直到 IOLoop.start 也已返回。在呼叫之前安排的一些工作 stop 可能仍在运行之前 IOLoop 关闭。

IOLoop.run_sync(func: Callable, timeout: Optional[float] = None) Any[源代码]

开始 IOLoop ,运行给定的函数,并停止循环。

函数必须返回可等待的对象或 None . 如果函数返回一个可等待的对象, IOLoop 将一直运行,直到等待解决(和 run_sync() 将返回等待的结果)。如果它引发了一个异常, IOLoop 将停止并向调用方重新引发异常。

仅限关键字的参数 timeout 可用于设置功能的最大持续时间。如果超时到期,则会引发 asyncio.TimeoutError 都被养大了。

此方法对于允许在 main() 功能:

async def main():
    # do stuff...

if __name__ == '__main__':
    IOLoop.current().run_sync(main)

在 4.3 版更改: 返回一个非``无`,不可等待的值现在是一个错误。

在 5.0 版更改: 如果发生超时,则 func 协程将取消。

在 6.2 版更改: tornado.util.TimeoutError 现在是的别名 asyncio.TimeoutError

IOLoop.close(all_fds: bool = False) None[源代码]

关闭 IOLoop ,释放所有使用的资源。

如果 all_fds 如果为真,则将关闭在IOLoop上注册的所有文件描述符(而不仅仅是由 IOLoop 本身)。

许多应用程序将只使用一个 IOLoop 在整个进程的生命周期中运行。在这种情况下,关闭 IOLoop 不需要,因为当进程退出时,所有内容都将被清除。 IOLoop.close 主要用于单元测试等场景,这些场景创建和销毁大量 IOLoops .

IOLoop 必须完全停止才能关闭。这意味着 IOLoop.stop() 必须被称为 and IOLoop.start() 必须允许返回才能尝试调用 IOLoop.close() . 因此呼吁 close 通常会在呼叫后出现 start 而不是在电话附近 stop .

在 3.1 版更改: 如果 IOLoop 实现支持“文件描述符”的非整数对象,这些对象将具有 close 方法时 all_fds 是真的。

static IOLoop.instance() tornado.ioloop.IOLoop[源代码]

的别名已弃用 IOLoop.current() .

在 5.0 版更改: 在此之前,此方法返回了全局单例 IOLoop 与每根线形成对比 IOLoop 返回的 current() . 在几乎所有的情况下,这两个线程都是相同的(当它们不同时,通常使用非Tornado线程来与主线程的 IOLoop )这种区别不存在于 asyncio ,因此为了便于与该包集成 instance() 已更改为别名 current() . 使用跨线程通信方面的应用程序 instance() 应该改为将自己的全局变量设置为指向 IOLoop 他们想用。

5.0 版后已移除.

IOLoop.install() None[源代码]

的别名已弃用 make_current() .

在 5.0 版更改: 在此之前,此方法将设置 IOLoop 作为 IOLoop.instance() . 既然 instance() 是一个别名 current()install() 是一个别名 make_current() .

5.0 版后已移除.

static IOLoop.clear_instance() None[源代码]

的别名已弃用 clear_current() .

在 5.0 版更改: 在此之前,此方法将清除 IOLoop 用作全局单例 IOLoop.instance() . 既然 instance() 是一个别名 current()clear_instance() 是一个别名 clear_current() .

5.0 版后已移除.

输入输出事件

IOLoop.add_handler(fd: int, handler: Callable[[int, int], None], events: int) None[源代码]
IOLoop.add_handler(fd: tornado.ioloop._S, handler: Callable[[tornado.ioloop._S, int], None], events: int) None

注册给定的处理程序以接收 fd .

这个 fd 参数可以是一个整型文件描述符,也可以是一个具有 fileno()close() 方法。

这个 events 参数是常量的位或 IOLoop.READIOLoop.WRITEIOLoop.ERROR .

当事件发生时, handler(fd, events) 将运行。

在 4.0 版更改: 除了原始文件描述符之外,还增加了传递类似文件的对象的能力。

IOLoop.update_handler(fd: Union[int, tornado.ioloop._Selectable], events: int) None[源代码]

改变我们倾听的事件 fd .

在 4.0 版更改: 除了原始文件描述符之外,还增加了传递类似文件的对象的能力。

IOLoop.remove_handler(fd: Union[int, tornado.ioloop._Selectable]) None[源代码]

停止侦听上的事件 fd .

在 4.0 版更改: 除了原始文件描述符之外,还增加了传递类似文件的对象的能力。

回调和超时

IOLoop.add_callback(callback: Callable, *args: Any, **kwargs: Any) None[源代码]

在下一个I/O循环迭代中调用给定的回调。

在任何时候从任何线程调用此方法都是安全的,信号处理程序除外。注意这是 only 方法在 IOLoop 这使得线程的安全性得到保证;与 IOLoop 必须从那开始 IOLoop 的线索。 add_callback() 可用于将控制从其他线程传输到 IOLoop 的线索。

要从信号处理程序添加回调,请参见 add_callback_from_signal .

IOLoop.add_callback_from_signal(callback: Callable, *args: Any, **kwargs: Any) None[源代码]

在下一个I/O循环迭代中调用给定的回调。

可以从python信号处理程序安全地使用;否则不应使用。

IOLoop.add_future(future: Union[Future[_T], concurrent.futures.Future[_T]], callback: Callable[[Future[_T]], None]) None[源代码]

在上调度回调 IOLoop 当给定 Future 完成了。

调用回调时使用一个参数,即 Future .

此方法只接受 Future 物体而不是其他等待物(不像 Tornado 中的大多数,两者可以互换)。

IOLoop.add_timeout(deadline: Union[float, datetime.timedelta], callback: Callable, *args: Any, **kwargs: Any) object[源代码]

运行 callback 当时 deadline 从I/O循环。

返回可传递给 remove_timeout 取消。

deadline 可以是表示时间的数字(与 IOLoop.time ,正常情况下 time.timedatetime.timedelta 对象,用于相对于当前时间的截止时间。自从 Tornado 4.0以来, call_later 对于相对情况来说是一个更方便的选择,因为它不需要TimeDelta对象。

注意打电话不安全 add_timeout 从其他线程。相反,你必须使用 add_callback 将控制权转移到 IOLoop 的线程,然后调用 add_timeout 从那里。

IOLoop的子类必须实现 add_timeoutcall_at ;每个的默认实现将调用另一个。 call_at 通常更容易实现,但希望与4.0之前的Tornado版本保持兼容性的子类必须使用 add_timeout 相反。

在 4.0 版更改: 现在通过 *args**kwargs 回拨电话。

IOLoop.call_at(when: float, callback: Callable, *args: Any, **kwargs: Any) object[源代码]

运行 callback 在指定的绝对时间 when .

when 必须是使用与相同参考点的数字 IOLoop.time .

返回可传递给 remove_timeout 取消。注意,与 asyncio 方法的名称相同,返回的对象没有 cancel() 方法。

add_timeout 有关线程安全和子类化的注释。

4.0 新版功能.

IOLoop.call_later(delay: float, callback: Callable, *args: Any, **kwargs: Any) object[源代码]

运行 callback 之后 delay 几秒钟过去了。

返回可传递给 remove_timeout 取消。注意,与 asyncio 方法的名称相同,返回的对象没有 cancel() 方法。

add_timeout 有关线程安全和子类化的注释。

4.0 新版功能.

IOLoop.remove_timeout(timeout: object) None[源代码]

取消挂起的超时。

参数是由返回的句柄 add_timeout . 打电话是安全的 remove_timeout 即使回调已经运行。

IOLoop.spawn_callback(callback: Callable, *args: Any, **kwargs: Any) None[源代码]

在下一个IOLoop迭代中调用给定的回调。

从Tornado 6.0开始,该方法相当于 add_callback .

4.0 新版功能.

IOLoop.run_in_executor(executor: Optional[concurrent.futures._base.Executor], func: Callable[[...], tornado.ioloop._T], *args: Any) Awaitable[tornado.ioloop._T][源代码]

在中运行函数 concurrent.futures.Executor .如果 executorNone ,将使用IO循环的默认执行器。

使用 functools.partial 将关键字参数传递给 func .

5.0 新版功能.

IOLoop.set_default_executor(executor: concurrent.futures._base.Executor) None[源代码]

设置与一起使用的默认执行器 run_in_executor() .

5.0 新版功能.

IOLoop.time() float[源代码]

根据返回当前时间 IOLoop 钟。

返回值是相对于过去未指定时间的浮点数。

历史上,IOLoop可以定制为使用例如 time.monotonic 而不是 time.time ,但当前不支持此方法,因此此方法等效于 time.time .

class tornado.ioloop.PeriodicCallback(callback: Callable[[], Optional[Awaitable]], callback_time: Union[datetime.timedelta, float], jitter: float = 0)[源代码]

安排定期调用给定的回调。

回调调用的频率为 callback_time 毫秒时 callback_time 是一个浮点。请注意,超时以毫秒为单位,而Tornado中的大多数其他与时间相关的函数使用秒。 callback_time 也可以作为 datetime.timedelta 对象。

如果 jitter 如果指定,则每个回调时间将在 jitter * callback_time 毫秒。抖动可用于减少具有类似周期的事件的对齐。抖动0.1意味着允许回拨时间有10%的变化。窗口居中 callback_time 因此,给定间隔内的调用总数不应受到添加抖动的显著影响。

如果回调运行时间超过 callback_time 毫秒,随后的调用将被跳过以恢复计划。

start 必须在 PeriodicCallback 创建。

在 5.0 版更改: 这个 io_loop 已删除参数(自4.1版以来已弃用)。

在 5.1 版更改: 这个 jitter 参数已添加。

在 6.2 版更改: 如果 callback 参数是协程,并且回调运行的时间长于 callback_time ,后续调用将被跳过。以前,这只适用于常规函数,而不适用于协程,因为协程对于以下对象是“即发即忘”的 PeriodicCallback

start() None[源代码]

启动计时器。

stop() None[源代码]

停止计时器。

is_running() bool[源代码]

返回 True 如果这样 PeriodicCallback 已启动。

4.1 新版功能.