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去除文件中空格、Tab及回车的方法
Apr 12 Python
Python中在for循环中嵌套使用if和else语句的技巧
Jun 20 Python
python实现生命游戏的示例代码(Game of Life)
Jan 24 Python
使用python和pygame绘制繁花曲线的方法
Feb 24 Python
python3.X 抓取火车票信息【修正版】
Jun 19 Python
python判断一个数是否能被另一个整数整除的实例
Dec 12 Python
Python3 使用cookiejar管理cookie的方法
Dec 28 Python
python 字典的打印实现
Sep 26 Python
python简单实现最大似然估计&scipy库的使用详解
Apr 15 Python
Python参数传递机制传值和传引用原理详解
May 22 Python
python 爬取百度文库并下载(免费文章限定)
Dec 04 Python
python中Mako库实例用法
Dec 31 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生成及获取JSON文件的方法
2016/08/23 PHP
浅析LigerUi开发中谨慎载入common.css文件
2013/07/09 Javascript
JavaScript限定复选框的选择个数示例代码
2013/08/25 Javascript
扩展IE中一些不兼容的方法如contains、startWith等等
2014/01/09 Javascript
js打开新窗口方法整理
2014/02/17 Javascript
jQuery中toggle()函数的使用实例
2015/04/17 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
利用Angularjs和bootstrap实现购物车功能
2016/08/31 Javascript
AngularJs expression详解及简单示例
2016/09/01 Javascript
js中获取键盘事件的简单实现方法
2016/10/10 Javascript
jQuery焦点图左右转换效果
2016/12/12 Javascript
JavaScript原生编写《飞机大战坦克》游戏完整实例
2017/01/04 Javascript
深入理解javascript中的 “this”
2017/01/17 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
JS简单生成随机数(随机密码)的方法
2017/05/11 Javascript
Webpack执行命令参数详解
2017/06/17 Javascript
JavaScript中AOP的实现与应用
2019/05/06 Javascript
原生js实现抽奖小游戏
2019/06/27 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
JS highcharts实现动态曲线代码示例
2020/10/16 Javascript
vue中实现点击空白区域关闭弹窗的两种方法
2020/12/30 Vue.js
利用Python命令行传递实例化对象的方法
2016/11/02 Python
python3中获取文件当前绝对路径的两种方法
2018/04/26 Python
对python dataframe逻辑取值的方法详解
2019/01/30 Python
Python3列表内置方法大全及示例代码小结
2019/05/10 Python
django基于cors解决跨域请求问题详解
2019/08/06 Python
Python numpy数组转置与轴变换
2019/11/15 Python
Python连接mysql方法及常用参数
2020/09/01 Python
css3实现背景颜色渐变让图片不再是唯一的实现方式
2012/12/18 HTML / CSS
Koral官方网站:女性时尚运动服
2019/04/10 全球购物
工程部经理岗位职责
2013/12/08 职场文书
表彰先进集体通报
2014/01/12 职场文书
企业业务员岗位职责
2014/03/14 职场文书
调研座谈会发言材料
2014/08/23 职场文书
党员教师个人对照检查材料(群众路线)
2014/09/26 职场文书
Pytorch可视化的几种实现方法
2021/06/10 Python