因此,我一直在研究如何编写异步代码,并得出了以下代码:
我有以下两个问题:
- 我们怎么能假设这个代码是异步的呢?我们只是想依赖这样一个事实,即使用gen模块使其异步(当然,我们需要为gen协程编写异步模块(
- 为什么龙卷风包含一个主线?我们可以让一个主线程链接到一个线程池,该线程池链接到另一个线程库吗?这个问题更倾向于我们用一个主线实现什么
from tornado import gen
import tornado.web
import tornado.ioloop
import motor
class MainHandler(tornado.web.RequestHandler):
@tornado.web.asynchronous
@gen.coroutine
def get(self):
post = yield db.user.find_one()
print post
self.write(post['name'])
handlers=[(
(r'/', MainHandler)
)]
db = motor.MotorClient().example
if __name__ == '__main__':
application = tornado.web.Application(handlers,debug=True)
application.listen(8888)
tornado.ioloop.IOLoop.instance().start()
异步性是接口的属性;使用@gen.coroutine
就足以使该处理程序异步,因为它会更改接口(返回Future
。顺便说一句,这里不需要使用@asynchronous
装饰器;由于Tornado 3.1,仅使用@coroutine
装饰器就足够了(。此外,由于Motor返回要生成的Futures
,我们知道它也是异步的。
阻止是实现的属性;你真正要问的是我们如何知道这个处理程序是否是非阻塞的。不幸的是,这是一个更棘手的问题。我们从Motor的文件中知道,它的设计和意图是非阻塞的,但没有简单的方法来验证它实际上是完全非阻塞的。在http://www.tornadoweb.org/en/stable/guide/async.html.
Tornado使用单个主线程,因为单线程非阻塞系统可以实现比线程系统更高的性能(尤其是考虑到python GIL的限制时(,而且通常不需要担心线程安全问题,这抵消了使所有内容异步的复杂性。
编写异步代码的最佳方式是编写类/函数。然后调用类/函数。此方法允许事件循环以处理回调。看看下面的代码示例,这里有函数创建,然后将该函数用作回调。这个(agian(是允许事件循环以异步方式进行回调。
from tornado.httpclient import AsyncHTTPClient
def asynchronous_fetch(url, callback):
http_client = AsyncHTTPClient()
def handle_response(response):
callback(response.body)
http_client.fetch(url, callback=handle_response)