use*_*407 8 python asynchronous tornado
我想找到简单的异步服务器示例.我有很多等待,数据库事务等功能:等等:
def blocking_task(n):
for i in xrange(n):
print i
sleep(1)
return i
Run Code Online (Sandbox Code Playgroud)
我需要在没有阻塞的情况下在分离的进程中运行它 可能吗?
dan*_*ano 16
Tornado旨在在单个线程中运行所有操作,但利用异步I/O来尽可能避免阻塞.如果您正在使用的数据库具有异步Python绑定(理想情况下适用于Tornado,例如适用于MongoDB的Motor或适用于Postgres的momoko),那么您将能够在不阻塞服务器的情况下运行数据库查询; 不需要单独的进程或线程.
为了解决您给出的确切示例,在哪里time.sleep(1)调用,您可以使用此方法通过龙卷风协同程序异步执行:
#!/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()
Run Code Online (Sandbox Code Playgroud)
有趣的是async_sleep.该方法正在创建一个异步Task,它正在调用该ioloop.add_timeout方法.add_timeout将在给定的秒数后运行指定的回调,而不会在等待超时到期时阻止ioloop.它期望两个论点:
add_timeout(deadline, callback) # deadline is the number of seconds to wait, callback is the method to call after deadline.
Run Code Online (Sandbox Code Playgroud)
正如您在上面的示例中所看到的,我们实际上只是add_timeout在代码中明确地提供了一个参数,这意味着我们最终会这样:
add_timeout(time.time() + seconds, ???)
Run Code Online (Sandbox Code Playgroud)
我们没有提供预期的回调参数.实际上,在gen.Task执行时add_timeout,它会callback在显式提供的参数的末尾附加关键字参数.所以这:
yield gen.Task(loop.add_timeout, time.time() + seconds)
Run Code Online (Sandbox Code Playgroud)
结果在gen.Task()中执行:
loop.add_timeout(time.time() + seconds, callback=gen.Callback(some_unique_key))
Run Code Online (Sandbox Code Playgroud)
在gen.Callback超时后执行时,它表示gen.Task完成,程序执行将继续到下一行.这种流程很难完全理解,至少在开始时(当我第一次阅读它时,它肯定适合我).阅读Tornado gen模块文档几次可能会有所帮助.
import tornado.web
from tornado.ioloop import IOLoop
from tornado import gen
from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor # `pip install futures` for python2
MAX_WORKERS = 16
class TestHandler(tornado.web.RequestHandler):
executor = ThreadPoolExecutor(max_workers=MAX_WORKERS)
"""
In below function goes your time consuming task
"""
@run_on_executor
def background_task(self):
sm = 0
for i in range(10 ** 8):
sm = sm + 1
return sm
@tornado.gen.coroutine
def get(self):
""" Request that asynchronously calls background task. """
res = yield self.background_task()
self.write(str(res))
class TestHandler2(tornado.web.RequestHandler):
@gen.coroutine
def get(self):
self.write('Response from server')
self.finish()
application = tornado.web.Application([
(r"/A", TestHandler),
(r"/B", TestHandler2),
])
application.listen(5000)
IOLoop.instance().start()
Run Code Online (Sandbox Code Playgroud)
当您运行上面的代码时,您可以在http://127.0.0.1:5000/A上运行计算成本高昂的操作,这不会阻止执行,请在访问后立即访问 http://127.0.0.1:5000/B http://127.0.0.1:5000/A.
| 归档时间: |
|
| 查看次数: |
16087 次 |
| 最近记录: |