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 18 Python
举例讲解如何在Python编程中进行迭代和遍历
Jan 19 Python
Python基于opencv的图像压缩算法实例分析
May 03 Python
Python中跳台阶、变态跳台阶与矩形覆盖问题的解决方法
May 19 Python
python调用matlab的m自定义函数方法
Feb 18 Python
python实现数据分析与建模
Jul 11 Python
Python 正则表达式 re.match/re.search/re.sub的使用解析
Jul 22 Python
python实现删除列表中某个元素的3种方法
Jan 15 Python
python实现高斯投影正反算方式
Jan 17 Python
django迁移文件migrations的实现
Mar 31 Python
python 制作python包,封装成可用模块教程
Jul 13 Python
python基于turtle绘制几何图形
Jun 15 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 动态生成静态HTML页面示例代码
2014/01/15 PHP
JS异常处理try..catch语句的作用和实例
2014/05/05 PHP
PHP MVC框架路由学习笔记
2016/03/02 PHP
PHP调用全国天气预报数据接口查询天气示例
2019/02/20 PHP
用prototype实现的简单小巧的多级联动菜单
2007/03/24 Javascript
10个基于jQuery或JavaScript的WYSIWYG 编辑器整理
2010/05/06 Javascript
mysql输出数据赋给js变量报unterminated string literal错误原因
2010/05/22 Javascript
JQuery浮动DIV提示信息并自动隐藏的代码
2010/08/29 Javascript
使用jQuery和PHP实现类似360功能开关效果
2014/02/12 Javascript
使用js画图之画切线
2015/01/12 Javascript
JavaScript实现横线提示输入验证码随输入验证码输入消失的方法
2016/09/24 Javascript
js实现五星评价功能
2017/03/08 Javascript
鼠标拖动改变DIV等网页元素的大小的实现方法
2017/07/06 Javascript
Vue cli 引入第三方JS和CSS的常用方法分享
2018/01/20 Javascript
js删除数组中的元素delete和splice的区别详解
2018/02/03 Javascript
webstorm中配置Eslint的两种方式及差异比较详解
2018/10/19 Javascript
微信小程序实现人脸识别登陆的示例代码
2019/04/02 Javascript
TypeScript开发Node.js程序的方法
2019/04/30 Javascript
浅谈ECMAScript 中的Array类型
2019/06/10 Javascript
nuxt框架中对vuex进行模块化设置的实现方法
2019/09/06 Javascript
JavaScript如何使用插值实现图像渐变
2020/06/28 Javascript
Nuxt 嵌套路由nuxt-child组件用法(父子页面组件的传值)
2020/11/05 Javascript
[36:02]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第一局
2016/02/28 DOTA
python 队列详解及实例代码
2016/10/18 Python
python选取特定列 pandas iloc,loc,icol的使用详解(列切片及行切片)
2019/08/06 Python
python使用docx模块读写docx文件的方法与docx模块常用方法详解
2020/02/17 Python
tensorflow 实现数据类型转换
2020/02/17 Python
Python matplotlib可视化实例解析
2020/06/01 Python
推荐10个CSS3 制作的创意下拉菜单效果
2014/02/11 HTML / CSS
Kivari官网:在线购买波西米亚服装
2018/10/29 全球购物
检讨书1000字
2014/10/11 职场文书
2016大学自主招生推荐信范文
2015/03/23 职场文书
淘宝文案策划岗位职责
2015/04/14 职场文书
四十年同学聚会致辞
2015/07/28 职场文书
2016年妇联“6﹒26国际禁毒日”宣传活动总结
2016/04/05 职场文书
Three.js实现雪糕地球的使用示例详解
2022/07/07 Javascript