简介
在 Tornado web 框架中,@tornado.gen.coroutine
是一个装饰器,用于简化异步代码的编写。它使得开发者可以像编写同步代码一样编写异步代码,而不必显式地处理回调或 yield
协程。
在 Tornado 的早期版本中,异步操作通常涉及回调或显式地管理协程。但是,随着 Python 的 asyncio
库和 Tornado 对其的集成,@tornado.gen.coroutine
装饰器成为了一种更简洁的方式来处理异步操作。
例子
使用 @tornado.gen.coroutine
装饰器,你可以编写一个看似同步的函数,但在函数内部使用 yield
关键字来等待异步操作(如网络请求或数据库查询)的完成。当 yield
表达式的结果准备好时,函数会恢复执行。
下面是一个使用 @tornado.gen.coroutine
的简单示例:
import tornado.ioloop
import tornado.web
import tornado.gen
import asyncio
class MainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
# 模拟一个异步操作,比如网络请求或数据库查询
result = yield asyncio.sleep(1) # 假设这是一个异步操作,这里用 sleep 代替
self.write("异步操作完成,结果是:%s" % result)
self.finish()
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
MainHandler
的 get
方法被 @tornado.gen.coroutine
装饰器修饰。在 get
方法内部,我们使用 yield
来等待 asyncio.sleep(1)
这个模拟的异步操作完成。当 sleep
完成时,get
方法会继续执行,并返回结果给客户端。
async
/await
简介
从 Tornado 5.0 开始,推荐使用原生的 async
/await
语法来编写异步代码,而不是使用 @tornado.gen.coroutine
。async
/await
语法更加直观,易于理解,并且与 Python 的 asyncio
库集成得更好。如果你使用的是 Tornado 5.0 或更高版本,建议使用 async
/await
语法来编写异步代码。
例子
import tornado.ioloop
import tornado.web
import asyncio
class MainHandler(tornado.web.RequestHandler):
async def get(self):
# 模拟一个异步操作,比如网络请求或数据库查询
result = await asyncio.sleep(1) # 假设这是一个异步操作,这里用 sleep 代替
self.write("异步操作完成,结果是:%s" % result)
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
在上面的代码中,我们定义了一个 MainHandler
类,它继承自 tornado.web.RequestHandler
。get
方法现在被定义为一个 async
方法,这意味着它是一个异步方法,并且可以使用 await
关键字来等待异步操作。
在 get
方法内部,我们使用 await asyncio.sleep(1)
来模拟一个异步操作。await
关键字会暂停 get
方法的执行,直到 asyncio.sleep(1)
完成并返回结果。一旦 sleep
完成,get
方法会恢复执行,并继续处理请求。
注意,我们不再需要 @tornado.gen.coroutine
装饰器,因为 async/await
语法已经内置了对异步操作的支持。
当运行此代码时,Tornado 服务器会监听 8888 端口。当你访问根路径 /
时,服务器会异步等待 1 秒(模拟异步操作),然后返回 “异步操作完成,结果是:None”,因为 asyncio.sleep(1)
不返回任何值(即 None
)。
在实际应用中,你可能会用 await
来等待真正的异步操作,比如 HTTP 请求、数据库查询等,这些操作通常由 Tornado 的异步客户端或第三方库(如 aiomysql
用于异步 MySQL 操作)提供。