tornado.ioloop — Main event loop

非阻塞套接字的I / O事件循环.

在Tornado 6.0中, IOLoopasyncio事件循环的包装,出于历史原因,其接口略有不同. 应用程序可以直接使用IOLoop接口或基础asyncio事件循环(除非需要与旧版Tornado兼容,在这种情况下必须使用IOLoop ).

Typical applications will use a single IOLoop object, accessed via IOLoop.current class method. The IOLoop.start method (or equivalently, asyncio.AbstractEventLoop.run_forever) should usually be called at the end of the main() function. Atypical applications may use more than one IOLoop, such as one IOLoop per thread, or per unittest case.

IOLoop objects

class tornado.ioloop.IOLoop[source]

I / O事件循环.

从Tornado 6.0开始, IOLoopasyncio事件循环的包装器.

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

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 socket.error as e:
            if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN):
                raise
            return
        connection.setblocking(0)
        io_loop = tornado.ioloop.IOLoop.current()
        io_loop.spawn_callback(handle_connection, connection, address)

if __name__ == '__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)
    io_loop.start()

默认情况下,除非已经存在当前IOLoop ,否则新构造的IOLoop成为线程的当前IOLoop . 可以使用IOLoop构造函数的make_current参数控制此行为:如果make_current=True ,则新的IOLoop将始终尝试变为当前状态,如果已经存在当前实例,则会引发错误. 如果make_current=False ,则新的IOLoop将不会尝试成为最新的.

通常, IOLoop无法以派生方式生存,也无法以任何方式在进程之间共享. 当使用多个进程时,每个进程应创建自己的IOLoop ,这还意味着依赖IOLoop任何对象(例如AsyncHTTPClient )也必须在子进程中创建. 作为指导原则,任何启动进程的操作(包括tornado.processmultiprocessing模块)都应尽早这样做,理想情况下,应用程序将其配置加载到main()后首先要做的事情.

在版本4.2中进行了更改:IOLoop构造函数中添加了make_current关键字参数.

在版本5.0中更改:默认情况下使用asyncio事件循环. IOLoop.configure方法不能在Python 3上使用,除非要冗余地指定asyncio事件循环.

Running an IOLoop

static IOLoop.current(instance: bool = True) → Optional[tornado.ioloop.IOLoop][source]

Returns the current thread’s IOLoop.

如果IOLoop正在运行或已被标记为当前make_current ,返回该实例. 如果没有当前IOLoop并且instance为true,则创建一个.

在版本4.1中进行了更改:添加了instance参数以控制对IOLoop.instance()的后备.

在版本5.0中进行了更改:在Python 3上,当前IOLoop控制权委托给asyncio ,此方法和其他方法作为传递访问器. 现在, instance参数控制是否在没有IOLoop时自动创建IOLoop ,而不是是否退回到IOLoop.instance() (现在是此方法的别名). 不建议使用instance=False ,因为即使我们不创建IOLoop ,此方法也可能会初始化asyncio循环.

IOLoop.make_current() → None[source]

IOLoop成为当前线程的IOLoop .

IOLoop在启动时会自动成为其线程的当前线程,但是有时在启动IOLoop之前显式调用make_current很有用,这样在启动时运行的代码可以找到正确的实例.

在版本4.1中进行了更改: An IOLoop created while there is no current IOLoop will automatically become current.

在版本5.0中更改:此方法还设置当前的asyncio事件循环.

static IOLoop.clear_current() → None[source]

清除当前线程的IOLoop .

主要用于测试之间的测试框架.

在版本5.0中更改:此方法asyncio除了当前的asyncio事件循环.

IOLoop.start() → None[source]

启动I / O循环.

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

IOLoop.stop() → None[source]

停止I / O循环.

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

请注意,即使在调用stop之后, IOLoop也不会完全停止,直到IOLoop.start也返回为止. 在IOLoop关闭之前,可能仍要运行在stop调用之前安排的某些工作.

IOLoop.run_sync(func: Callable, timeout: float = None) → Any[source]

启动IOLoop ,运行给定功能,然后停止循环.

该函数必须返回一个等待对象或None . 如果函数返回一个等待对象,则IOLoop将运行直到解析了等待对象为止(而run_sync()将返回等待对象的结果). 如果引发异常,则IOLoop将停止,并将异常重新引发给调用方.

仅关键字参数timeout可以用于设置函数的最大持续时间. 如果超时到期, tornado.util.TimeoutError引发tornado.util.TimeoutError .

此方法对于允许在main()函数中进行异步调用非常有用:

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

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

在版本4.3中进行了更改:现在,返回非None ,不可等待的值是一个错误.

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

IOLoop.close(all_fds: bool = False) → None[source]

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

If all_fds is true, all file descriptors registered on the IOLoop will be closed (not just the ones created by the IOLoop itself).

许多应用程序将只使用单个IOLoop ,该IOLoop在该过程的整个生命周期内运行. 在那种情况下, IOLoop关闭IOLoop因为在进程退出时,所有东西都会被清除. IOLoop.close主要提供给诸如单元测试之类的场景,这些场景会创建和销毁大量的IOLoops .

必须先完全停止IOLoop然后才能将其关闭. 这意味着, IOLoop.stop()必须被调用 IOLoop.start()必须被允许尝试调用之前返回IOLoop.close() 因此, close呼叫通常会在start呼叫之后立即出现,而不是在stop呼叫附近出现.

在版本3.1中更改:如果IOLoop实现支持"文件描述符"的非整数对象,则当all_fds为true时,这些对象将具有其close方法.

static IOLoop.instance() → tornado.ioloop.IOLoop[source]

IOLoop.current()已弃用别名.

在版本5.0中进行了更改:以前,此方法返回了全局单例IOLoop ,这与current()返回的每线程IOLoop相反. 在几乎所有情况下,两者都是相同的(当它们不同时,通常在非Tornado线程中使用它来与主线程的IOLoop ). 这种区别在asyncio不存在,因此为了促进与该包的集成,将instance()更改为current()的别名. 使用instance()的跨线程通信方面的应用程序应该设置自己的全局变量,以指向要使用的IOLoop .

从5.0版开始不推荐使用.

IOLoop.install() → None[source]

不推荐使用的make_current()别名.

在版本5.0中更改:以前,此方法会将此IOLoop设置为IOLoop.instance()使用的全局单例. 现在, instance()current()的别名, install()make_current()的别名.

Deprecated since version 5.0.

static IOLoop.clear_instance() → None[source]

clear_current()已弃用别名.

改变在5.0版本:以前,此方法将清除IOLoop作为全球单由IOLoop.instance() 现在, instance()current()的别名, clear_instance()clear_current()的别名.

从5.0版开始不推荐使用.

I/O events

IOLoop.add_handler(fd: Union[int, tornado.ioloop._Selectable], handler: Callable[[...], None], events: int) → None[source]

注册给定的处理程序以接收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[source]

更改我们监听fd的事件.

在版本4.0中进行了更改:除了原始文件描述符外,还添加了传递类似文件的对象的功能.

IOLoop.remove_handler(fd: Union[int, tornado.ioloop._Selectable]) → None[source]

停止监听fd事件.

在版本4.0中更改: Added the ability to pass file-like objects in addition to raw file descriptors.

Callbacks and timeouts

IOLoop.add_callback(callback: Callable, *args, **kwargs) → None[source]

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

除了从信号处理程序之外,随时可以从任何线程调用此方法是安全的. 请注意,这是唯一的方法IOLoop ,使这个线程安全的保证; 与IOLoop所有其他交互IOLoop必须在该IOLoop的线程中完成. add_callback()可用于将控制权从其他线程转移到IOLoop的线程.

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

IOLoop.add_callback_from_signal(callback: Callable, *args, **kwargs) → None[source]

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

可从Python信号处理程序安全使用; 否则不应使用.

IOLoop.add_future(future: Union[Future[_T], concurrent.futures.Future[_T]], callback: Callable[[Future[_T]], None]) → None[source]

当给定的Future完成时,在IOLoop上安排回调.

回调由一个参数Future调用.

此方法仅接受Future对象,而不接受其他可等待对象(与Tornado的大多数对象可互换)不同.

IOLoop.add_timeout(deadline: Union[float, datetime.timedelta], callback: Callable[[...], None], *args, **kwargs) → object[source]

Runs the callback at the time deadline from the I/O loop.

返回一个不透明的句柄,可以将其传递给remove_timeout来取消.

deadline可以是表示时间的数字(与IOLoop.time相同,通常为time.time ),或者是相对于当前时间的截止日期的datetime.timedelta对象. 从Tornado 4.0开始,由于不需要timedelta对象,因此call_later是相对情况下更方便的替代方法.

请注意,从其他线程调用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[[...], None], *args, **kwargs) → object[source]

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

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

返回一个不透明的句柄,可以将其传递给remove_timeout来取消. 注意,与同名的asyncio方法不同,返回的对象没有cancel()方法.

有关线程安全性和子类化的注释,请参见add_timeout .

版本4.0中的新功能.

IOLoop.call_later(delay: float, callback: Callable[[...], None], *args, **kwargs) → object[source]

经过delay秒数后运行callback .

返回一个不透明的句柄,可以将其传递给remove_timeout来取消. 注意,与同名的asyncio方法不同,返回的对象没有cancel()方法.

有关线程安全性和子类化的注释,请参见add_timeout .

版本4.0中的新功能.

IOLoop.remove_timeout(timeout: object) → None[source]

取消挂起的超时.

该参数是add_timeout返回的add_timeout . 即使回调已经运行,也可以安全地调用remove_timeout .

IOLoop.spawn_callback(callback: Callable, *args, **kwargs) → None[source]

在下一个IOLoop迭代上调用给定的回调.

从Tornado 6.0开始,此方法等效于add_callback .

版本4.0中的新功能.

IOLoop.run_in_executor(executor: Optional[concurrent.futures._base.Executor], func: Callable[[...], _T], *args) → Awaitable[_T][source]

运行在一个功能concurrent.futures.Executor . 如果executorNone ,则将使用IO循环的默认执行器.

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

5.0版中的新功能.

IOLoop.set_default_executor(executor: concurrent.futures._base.Executor) → None[source]

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

5.0版中的新功能.

IOLoop.time() → float[source]

根据IOLoop的时钟返回当前时间.

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

从历史上看,可以自定义IOLoop以使用例如time.monotonic代替time.time ,但是当前不支持此方法,因此此方法等效于time.time .

class tornado.ioloop.PeriodicCallback(callback: Callable[[], None], callback_time: float, jitter: float = 0)[source]

安排给定的回调被定期调用.

每个callback_time毫秒调用一次该回调. 请注意,超时以毫秒为单位,而Tornado中大多数其他与时间相关的功能都以秒为单位.

如果指定了jitter ,则将在jitter * callback_time毫秒的窗口内随机选择每个回调时间. 抖动可用于减少具有相似周期的事件的对齐. 0.1的抖动意味着允许回调时间有10%的变化. 该窗口以callback_time为中心,因此在给定时间间隔内的呼叫总数不应受到增加抖动的明显影响.

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

start must be called after the PeriodicCallback is created.

在5.0版中进行了更改: io_loop参数(从4.1版弃用)已被删除.

在版本5.1中更改:添加了jitter参数.

start() → None[source]

启动计时器.

stop() → None[source]

停止计时器.

is_running() → bool[source]

如果此PeriodicCallback已启动,则返回True .

4.1版中的新功能.