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小程序
Aug 15 Python
Python创建xml的方法
Mar 10 Python
python一键升级所有pip package的方法
Jan 16 Python
Django中间件工作流程及写法实例代码
Feb 06 Python
Python实现的个人所得税计算器示例
Jun 01 Python
Python3中函数参数传递方式实例详解
May 05 Python
pandas中的数据去重处理的实现方法
Feb 10 Python
Django框架models使用group by详解
Mar 11 Python
python 一维二维插值实例
Apr 22 Python
Matplotlib 绘制饼图解决文字重叠的方法
Jul 24 Python
python用tkinter实现一个gui的翻译工具
Oct 26 Python
Python 实现二叉查找树的示例代码
Dec 21 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
Content-type 的说明
2006/10/09 PHP
php strtotime 函数UNIX时间戳
2009/01/14 PHP
php session安全问题分析
2011/06/24 PHP
CentOS下PHP安装Oracle扩展
2015/02/15 PHP
php+redis实现注册、删除、编辑、分页、登录、关注等功能示例
2017/02/15 PHP
jsTree 基于JQuery的排序节点 Bug
2011/07/26 Javascript
javascript级联下拉列表实例代码(自写)
2013/05/10 Javascript
使用JavaScript的ActiveXObject对象检测应用程序是否安装的方法
2014/04/15 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
2014/04/20 Javascript
设计模式中的组合模式在JavaScript程序构建中的使用
2016/05/18 Javascript
JavaScript异步上传图片文件的实例代码
2017/07/04 Javascript
NW.js 简介与使用方法
2018/02/01 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
jQuery ajax仿Google自动提示SearchSuggess功能示例
2019/03/28 jQuery
layer.open 获取不到表单信息的解决方法
2019/09/26 Javascript
深入理解redux之compose的具体应用
2020/01/12 Javascript
VUE项目axios请求头更改Content-Type操作
2020/07/24 Javascript
vant 自定义 van-dropdown-item的用法
2020/08/05 Javascript
Angular进行简单单元测试的实现方法实例
2020/08/16 Javascript
python二分法实现实例
2013/11/21 Python
Python基于回溯法解决01背包问题实例
2017/12/06 Python
新手常见6种的python报错及解决方法
2018/03/09 Python
分享一下Python数据分析常用的8款工具
2018/04/29 Python
python绘制中国大陆人口热力图
2018/11/07 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
CSS3自定义滚动条样式的示例代码
2017/08/21 HTML / CSS
西班牙国家航空官方网站:Iberia
2017/11/16 全球购物
新加坡一家在线男士皮具品牌:Faire Leather Co.
2019/12/01 全球购物
党的群众路线教育实践活动对照检查材料(教师)
2014/09/24 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
师德先进个人材料
2014/12/20 职场文书
明星邀请函
2015/02/02 职场文书
2015中秋节晚会开场白
2015/07/30 职场文书
小学大队干部竞选稿
2015/11/20 职场文书
Python 快速验证代理IP是否有效的方法实现
2021/07/15 Python