Python的Tornado框架异步编程入门实例


Posted in Python onApril 24, 2015

Tornado

Tornado 是一款非阻塞可扩展的使用Python编写的web服务器和Python Web框架, 可以使用Tornado编写Web程序并不依赖任何web服务器直接提供高效的web服务.所以Tornado不仅仅是一个web框架而且还是一款可以用于生产环境的高效的web服务器

Torando 在Linux和FreeBSD上使用高效的异步I/O模型 epoll 和kqueue来实现高效的web服务器, 所以 tornado在Linux上和FreeBSD系列性能可以达到最高
接口

当然我们可以不仅仅把Tornado看作是一个web框架和web服务器, 我们可以利用Tornado提供的接口进行高效的网络异步编程,

tornado.ioloop.IOLoop 提供了三个接口可以用于网络编程:

add_handler

def add_handler(self, fd, handler, events):
  self._handlers[fd] = stack_context.wrap(handler)
  self._impl.register(fd, events | self.ERROR)

add_handler用于添加socket到主循环中, 接受三个参数: fd 是socket的文件描述符 handler 是处理此socket的 callback函数 * events 是此socket注册的事件

update_handler

def update_handler(self, fd, events):
  self._impl.modify(fd, events | self.ERROR)

update_handler用于更新住循环中已存在的socket响应事件, 接受两个参数: fd 是socket对应的文件描述符 events 是注册的新事件

remove_handler

def remove_handler(self, fd):
  self._handlers.pop(fd, None)
  self._events.pop(fd, None)
  try:
    self._impl.unregister(fd)
  except Exception:
    gen_log.debug("Error deleting fd from IOLoop", exc_info=True)

remove_handler用于移除主循环中已存在的socket
事件

tornado.ioloop.IOLoop同时提供了4种响应事件:
Python的Tornado框架异步编程入门实例

实例

根据上面的接口和事件我们就可以写出一个简单的 echo server

#!/usr/bin/env python
# -*- coding:utf-8 -*-
#
#  Author :  cold
#  E-mail :  wh_linux@126.com
#  Date  :  13/04/15 15:08:51
#  Desc  :  Tornado Echo Server
#  HOME  :  http://www.linuxzen.com
#
import Queue
import socket

from functools import partial

from tornado.ioloop import IOLoop

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)       # 将socket设置为非阻塞

server_address = ("localhost", 10000)

sock.bind(server_address)
sock.listen(5)

fd_map = {}       # 文件描述符到socket的映射
message_queue_map = {}  # socket到消息队列的映射

fd = sock.fileno()
fd_map[fd] = sock

ioloop = IOLoop.instance()

def handle_client(cli_addr, fd, event):
  s = fd_map[fd]
  if event & IOLoop.READ:
    data = s.recv(1024)
    if data:
      print "   received '%s' from %s" % (data, cli_addr)
      # 接收到消息更改事件为写, 用于发送数据到对端
      ioloop.update_handler(fd, IOLoop.WRITE)
      message_queue_map[s].put(data)
    else:
      print "   closing %s" % cli_addr
      ioloop.remove_handler(fd)
      s.close()
      del message_queue_map[s]

  if event & IOLoop.WRITE:
    try:
      next_msg = message_queue_map[s].get_nowait()
    except Queue.Empty:
      print "%s queue empty" % cli_addr
      ioloop.update_handler(fd, IOLoop.READ)
    else:
      print 'sending "%s" to %s' % (next_msg, cli_addr)
      s.send(next_msg)

  if event & IOLoop.ERROR:
    print " exception on %s" % cli_addr
    ioloop.remove_handler(fd)
    s.close()
    del message_queue_map[s]


def handle_server(fd, event):
  s = fd_map[fd]
  if event & IOLoop.READ:
    conn, cli_addr = s.accept()
    print "   connection %s" % cli_addr[0]
    conn.setblocking(0)
    conn_fd = conn.fileno()
    fd_map[conn_fd] = conn
    handle = partial(handle_client, cli_addr[0])  # 将cli_addr作为第一个参数
    # 将连接和handle注册为读事件加入到 tornado ioloop
    ioloop.add_handler(conn_fd, handle, IOLoop.READ)
    message_queue_map[conn] = Queue.Queue()  # 创建对应的消息队列


ioloop.add_handler(fd, handle_server, IOLoop.READ)

ioloop.start()

上面代码就建立了一个非阻塞的高效的异步的echo server

Python 相关文章推荐
python使用datetime模块计算各种时间间隔的方法
Mar 24 Python
浅析AST抽象语法树及Python代码实现
Jun 06 Python
Python列表推导式与生成器表达式用法示例
Feb 08 Python
python  文件的基本操作 菜中菜功能的实例代码
Jul 17 Python
Python爬虫:url中带字典列表参数的编码转换方法
Aug 21 Python
python使用多线程编写tcp客户端程序
Sep 02 Python
使用tensorboard可视化loss和acc的实例
Jan 21 Python
python文件和文件夹复制函数
Feb 07 Python
pygame用blit()实现动画效果的示例代码
May 28 Python
python入门教程之基本算术运算符
Nov 13 Python
Python关于拓扑排序知识点讲解
Jan 04 Python
pytorch中的model.eval()和BN层的使用
May 22 Python
使用Python的Tornado框架实现一个简单的WebQQ机器人
Apr 24 #Python
Python程序中使用SQLAlchemy时出现乱码的解决方案
Apr 24 #Python
简单说明Python中的装饰器的用法
Apr 24 #Python
使用基于Python的Tornado框架的HTTP客户端的教程
Apr 24 #Python
简单介绍Python的Tornado框架中的协程异步实现原理
Apr 23 #Python
解决Python中由于logging模块误用导致的内存泄露
Apr 23 #Python
粗略分析Python中的内存泄漏
Apr 23 #Python
You might like
用PHP和ACCESS写聊天室(九)
2006/10/09 PHP
ADODB结合SMARTY使用~超级强
2006/11/25 PHP
按上下级层次关系输出内容的PHP代码
2010/07/17 PHP
php fsockopen伪造post与get方法的详解
2013/06/14 PHP
PHP自毁程序(慎用)
2015/07/09 PHP
PHP数组内存利用率低和弱类型详细解读
2017/08/10 PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
2017/11/16 PHP
php实现的数组转xml案例分析
2019/09/28 PHP
JS焦点图切换,上下翻转
2011/05/12 Javascript
ExtJS下书写动态生成的xml(兼容火狐)
2013/04/02 Javascript
javascript中的取反再取反~~没有意义
2014/04/06 Javascript
jquery通过closest选择器修改上级元素的方法
2015/03/17 Javascript
AngualrJS中的Directive制作一个菜单
2016/01/26 Javascript
Asp.Net之JS生成分页条的方法
2016/11/23 Javascript
作为老司机使用 React 总结的 11 个经验教训
2017/04/08 Javascript
vue实现百度搜索下拉提示功能实例
2017/06/14 Javascript
详解angular笔记路由之angular-router
2017/09/12 Javascript
详解Node.js利用node-git-server快速搭建git服务器
2017/09/27 Javascript
Vue.js 的移动端组件库mint-ui实现无限滚动加载更多的方法
2017/12/23 Javascript
vue-week-picker实现支持按周切换的日历
2019/06/26 Javascript
python实现的阳历转阴历(农历)算法
2014/04/25 Python
Python实现生成随机数据插入mysql数据库的方法
2017/12/25 Python
django文档学习之applications使用详解
2018/01/29 Python
局域网内python socket实现windows与linux间的消息传送
2019/04/19 Python
python图形界面开发之wxPython树控件使用方法详解
2020/02/24 Python
Python爬虫之Spider类用法简单介绍
2020/08/04 Python
CSS3盒子模型详解
2013/04/24 HTML / CSS
html5拖曳操作 HTML5实现网页元素的拖放操作
2013/01/02 HTML / CSS
椰子猫砂:CatSpot
2018/08/27 全球购物
服装公司总经理岗位职责
2013/11/30 职场文书
模具专业求职信
2014/06/26 职场文书
关于车尾的标语大全
2015/08/11 职场文书
python 下载文件的几种方式分享
2021/04/07 Python
python中print格式化输出的问题
2021/04/16 Python
MySQL配置主从服务器(一主多从)
2021/08/07 MySQL
一次线上mongo慢查询问题排查处理记录
2022/03/18 MongoDB