Tornado 简单用法
callback 写法
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) def print_handler(body): print body.text url = 'http://www.baidu.com' for i in range(10): # 这里并不会阻塞,从而提高并发请求数量,提高吞吐量,服务可用性提高。 asynchronous_fetch(url, print_handler)
future 类写法
from tornado.concurrent import Future import time def async_fetch_future(url): http_client = AsyncHTTPClient() my_future = Future() fetch_future = http_client.fetch(url) fetch_future.add_done_callback( lambda f: my_future.set_result(f.result())) return my_future future = async_fetch_future(url) while not future.done(): time.sleep(1) future.result()
装饰器写法
from tornado import gen @gen.coroutine def fetch_coroutine(url): http_client = AsyncHTTPClient() response = yield http_client.fetch(url) raise gen.Return(response.body)
Python 2中生成器不允许return操作,因此tornado必须以抛出异常的形式接受返回值。
下面是一个使用 tornado ioloop 的异步TCP 服务器
import errno import functools import tornado.ioloop import socket import datetime def connection_ready(sock, fd, events): while True: try: connection, address = sock.accept() except socket.error as e: if e.args[0] not in (errno.EWOULDBLOCK, errno.EAGAIN): raise return connection.setblocking(0) handle_connection(connection, address) def recover_persistence(): print 'recover....' if __name__ == '__main__': port = 11111 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) sock.bind(("", port)) sock.listen(9999) io_loop = tornado.ioloop.IOLoop.instance() # tornado.ioloop.IOLoop.current() #Returns the current thread’s IOLoop. # IOLoop是个工厂,一般使用单列模式及 IOLoop.instance() 得到单列, #并且这个是主线程中的IOLoop, 其他线程要想得到主线程中的IOLoop就需要使用instance callback = functools.partial(connection_ready, sock) tornado.ioloop.IOLoop.instance().add_handler(sock.fileno(), callback, io_loop.READ) wait_auth = datetime.timedelta(seconds=2) tornado.ioloop.IOLoop.instance().add_timeout(wait_auth, recover_persistence) tornado.ioloop.IOLoop.instance().start()