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中的闭包用法实例详解
May 05 Python
使用SAE部署Python运行环境的教程
May 05 Python
Python文件及目录操作实例详解
Jun 04 Python
python编码总结(编码类型、格式、转码)
Jul 01 Python
Python面向对象之类的定义与继承用法示例
Jan 14 Python
Python批量修改图片分辨率的实例代码
Jul 04 Python
Django CBV类的用法详解
Jul 26 Python
python序列类型种类详解
Feb 26 Python
Python中SQLite如何使用
May 27 Python
Keras 切换后端方式(Theano和TensorFlow)
Jun 19 Python
Django-silk性能测试工具安装及使用解析
Nov 28 Python
使用Python爬虫爬取小红书完完整整的全过程
Jan 19 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中路径问题的解决方案
2006/10/09 PHP
在Mac OS上自行编译安装Apache服务器和PHP解释器
2015/12/24 PHP
php使用PDO事务配合表格读取大量数据插入操作实现方法
2017/02/16 PHP
PHP微信开发之微信录音临时转永久存储
2018/01/26 PHP
javascript 处理事件绑定的一些兼容写法
2009/12/24 Javascript
自写的一个jQuery圆角插件
2010/10/26 Javascript
DOM 中的事件处理介绍
2012/01/18 Javascript
基于jquery的用鼠标画出可移动的div
2012/09/06 Javascript
jQuery学习笔记 操作jQuery对象 属性处理
2012/09/19 Javascript
js+JQuery返回顶部功能如何实现
2012/12/03 Javascript
向左滚动文字 js代码效果
2013/08/17 Javascript
浅谈javascript原型链与继承
2015/07/13 Javascript
4种JavaScript实现简单tab选项卡切换的方法
2016/01/06 Javascript
angularJS Provider、factory、service详解及实例代码
2016/09/21 Javascript
JS实现的样式切换功能tableCSS实例
2016/12/30 Javascript
canvas 实现中国象棋
2017/02/17 Javascript
Webpack中雪碧图插件使用详解
2018/05/25 Javascript
微信网页授权并获取用户信息的方法
2018/07/30 Javascript
jQuery解析json格式数据示例
2018/09/01 jQuery
JavaScript this使用方法图解
2020/02/04 Javascript
javascript实现京东登录显示隐藏密码
2020/08/02 Javascript
Vue切换Tab动态渲染组件的操作
2020/09/21 Javascript
[13:18]《一刀刀一天》之DOTA全时刻21:详解TI新赛制 A队再露獠牙
2014/06/24 DOTA
Python 检查数组元素是否存在类似PHP isset()方法
2014/10/14 Python
深入理解Python中字典的键的使用
2015/08/19 Python
Python中http请求方法库汇总
2016/01/06 Python
Python中单、双下划线的区别总结
2017/12/01 Python
python实现生成Word、docx文件的方法分析
2019/08/30 Python
numpy 返回函数的上三角矩阵实例
2019/11/25 Python
python GUI库图形界面开发之PyQt5布局控件QVBoxLayout详细使用方法与实例
2020/03/06 Python
波兰品牌鞋履在线商店:Eastend.pl
2020/01/11 全球购物
小学生操行评语大全
2014/04/22 职场文书
幼儿园户外活动总结
2014/07/04 职场文书
玩手机检讨书1000字
2014/10/20 职场文书
学习十八届四中全会精神思想汇报
2014/10/23 职场文书
python实现语音常用度量方法的代码详解
2021/05/25 Python