龙卷风python的简单异步示例 [英] Simple async example with tornado python

查看:163
本文介绍了龙卷风python的简单异步示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到简单的异步服务器示例. 我有一些功能,需要大量的等待,数据库事务...等等:

I want find simple async server example. I have got some function with lot of wait, database transactions ... etc:

def blocking_task(n):
    for i in xrange(n):
        print i
        sleep(1)
    return i

我需要在单独的进程中运行它,而不会阻塞.有可能吗?

I need run it function in separated process without blocking. Is it possible?

推荐答案

Tornado旨在在单个线程中运行所有操作,但要利用异步I/O来尽可能避免阻塞.如果您使用的数据库具有异步Python绑定(理想情况下是专门针对Tornado的绑定),例如用于MongoDB的 Motor momoko (适用于Postgres),那么您就可以在不阻塞服务器的情况下运行数据库查询;不需要单独的进程或线程.

Tornado is designed to run all your operations in a single thread, but utilize asynchronous I/O to avoid blocking as much as possible. If the DB you're using has asychronous Python bindings (ideally ones geared for Tornado specifically, like Motor for MongoDB or momoko for Postgres), then you'll be able to run your DB queries without blocking the server; no separate processes or threads needed.

要解决您给出的确切示例(调用time.sleep(1)的示例),可以使用这种方法通过龙卷风协程异步执行此操作:

To address the exact example you gave, where time.sleep(1) is called, you could use this approach to do it asynchronously via tornado coroutines:

#!/usr/bin/python

import tornado.web
from tornado.ioloop import IOLoop
from tornado import gen 
import time

@gen.coroutine
def async_sleep(seconds):
    yield gen.Task(IOLoop.instance().add_timeout, time.time() + seconds)

class TestHandler(tornado.web.RequestHandler):
    @gen.coroutine
    def get(self):
        for i in xrange(100):
            print i
            yield async_sleep(1)
        self.write(str(i))
        self.finish()


application = tornado.web.Application([
    (r"/test", TestHandler),
    ])  

application.listen(9999)
IOLoop.instance().start()

有趣的部分是async_sleep.该方法正在创建一个异步Task,该任务正在调用ioloop.add_timeout方法. add_timeout将在给定的秒数后运行指定的回调,而不会在等待超时到期时阻止ioloop.它需要两个参数:

The interesting part is async_sleep. That method is creating an asynchronous Task, which is calling the ioloop.add_timeout method. add_timeout will run a specified callback after a given number of seconds, without blocking the ioloop while waiting for the timeout to expire. It expects two arguments:

add_timeout(deadline, callback) # deadline is the number of seconds to wait, callback is the method to call after deadline.

如您在上面的示例中看到的,我们实际上只是在代码中显式地为add_timeout提供了一个参数,这意味着我们可以这样做:

As you can see in the example above, we're only actually providing one parameter to add_timeout explicitly in the code, which means we end up this this:

add_timeout(time.time() + seconds, ???)

我们没有提供预期的回调参数.实际上,当gen.Task执行add_timeout时,会将callback关键字参数附加到显式提供的参数的末尾.因此:

We're not providing the expected callback parameter. In fact, when gen.Task executes add_timeout, it appends a callback keyword argument to the end of the explicitly provided parameters. So this:

yield gen.Task(loop.add_timeout, time.time() + seconds)

导致此结果在gen.Task()内部执行:

Results in this being executed inside gen.Task():

loop.add_timeout(time.time() + seconds, callback=gen.Callback(some_unique_key))

在超时后执行gen.Callback时,它表示gen.Task已完成,并且程序执行将继续到下一行.至少在一开始,这种流程有点难以完全理解(当我第一次阅读它时,肯定是对我来说).多次阅读 Tornado gen模块文档可能会有所帮助.

When gen.Callback is executed after the timeout, it signals that the gen.Task is complete, and the program execution will continue on to the next line. This flow is kind of difficult to fully understand, at least at first (it certainly was for me when I first read about it). It'll probably be helpful to read over the Tornado gen module documentation a few times.

这篇关于龙卷风python的简单异步示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆