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.process
和multiprocessing
模块)应该尽可能早地这样做,理想情况下,应用程序在加载其配置后要做的第一件事是main()
.在 4.2 版更改: 增加了
make_current
关键字参数IOLoop
建造师。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
,返回该实例。如果没有电流IOLoop
和instance
是真的,创造了一个。在 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
,以便在启动时运行的代码可以找到正确的实例。在 5.0 版更改: 此方法还设置当前
asyncio
事件循环。6.2 版后已移除: 在从Python3.10开始的Asyncio中,不推荐使用“当前”而不是当前正在运行的事件循环的概念。Tornado中的所有相关功能也已弃用。相反,使用以下命令开始事件循环
asyncio.run
在与它互动之前。
- static IOLoop.clear_current() None [源代码]¶
清除
IOLoop
对于当前线程。主要供测试框架在测试之间使用。
在 5.0 版更改: 此方法还清除当前
asyncio
事件循环。6.2 版后已移除.
- 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()
必须被称为 andIOLoop.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.READ
,IOLoop.WRITE
和IOLoop.ERROR
.当事件发生时,
handler(fd, events)
将运行。在 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.time
)datetime.timedelta
对象,用于相对于当前时间的截止时间。自从 Tornado 4.0以来,call_later
对于相对情况来说是一个更方便的选择,因为它不需要TimeDelta对象。注意打电话不安全
add_timeout
从其他线程。相反,你必须使用add_callback
将控制权转移到IOLoop
的线程,然后调用add_timeout
从那里。IOLoop的子类必须实现
add_timeout
或call_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
.如果executor
是None
,将使用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
。- is_running() bool [源代码]¶
返回
True
如果这样PeriodicCallback
已启动。4.1 新版功能.