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使用Beautiful Soup包编写爬虫时的一些关键点
Jan 20 Python
Python实现以时间换空间的缓存替换算法
Feb 19 Python
Python处理json字符串转化为字典的简单实现
Jul 07 Python
基于Python的关键字监控及告警
Jul 06 Python
Python 数据处理库 pandas 入门教程基本操作
Apr 19 Python
Python从函数参数类型引出元组实例分析
May 28 Python
OpenCV+Python--RGB转HSI的实现
Nov 27 Python
python不到50行代码完成了多张excel合并的实现示例
May 28 Python
Python Mock模块原理及使用方法详解
Jul 07 Python
Django def clean()函数对表单中的数据进行验证操作
Jul 09 Python
python - asyncio异步编程
Apr 06 Python
在pycharm中无法import所安装的库解决方案
May 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学习笔记 数组的常用函数
2011/06/13 PHP
PHP提取字符串中的图片地址[正则表达式]
2011/11/12 PHP
PHP防止sql注入小技巧之sql预处理原理与实现方法分析
2019/12/13 PHP
JS无限树状列表实现代码
2011/01/11 Javascript
jQuery动态添加 input type=file的实现代码
2012/06/14 Javascript
javascript之典型高阶函数应用介绍二
2013/01/10 Javascript
js时间日期和毫秒的相互转换
2013/02/22 Javascript
原生JavaScript实现连连看游戏(附源码)
2013/11/05 Javascript
javascript数组操作方法小结和3个属性详细介绍
2014/07/05 Javascript
JavaScript中最简洁的编码html字符串的方法
2014/10/11 Javascript
javascript实现完美拖拽效果
2015/05/06 Javascript
JS访问SWF的函数用法实例
2015/07/01 Javascript
JS使用eval()动态创建变量的方法
2016/06/03 Javascript
原生js代码实现图片放大境效果
2016/10/30 Javascript
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
VUE实现可随意拖动的弹窗组件
2018/09/25 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
2019/01/24 jQuery
jquery操作checkbox的常用方法总结【附测试源码下载】
2019/06/10 jQuery
浅析JavaScript 函数柯里化
2020/09/08 Javascript
python统计一个文本中重复行数的方法
2014/11/19 Python
python生成式的send()方法(详解)
2017/05/08 Python
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
Python实现学校管理系统
2018/01/11 Python
Centos7 Python3下安装scrapy的详细步骤
2018/03/15 Python
Python学习笔记之open()函数打开文件路径报错问题
2018/04/28 Python
aws 通过boto3 python脚本打pach的实现方法
2020/05/10 Python
HTML5中的Web Notification桌面通知功能的实现方法
2019/07/29 HTML / CSS
FitFlop澳大利亚官网:英国符合人体工学的鞋类品牌
2017/06/05 全球购物
兼职业务员岗位职责
2014/01/01 职场文书
情况说明书格式范文
2014/05/06 职场文书
环保倡议书50字
2014/05/15 职场文书
大三学生英语考试作弊检讨书
2015/01/01 职场文书
我们的节日元宵节活动总结
2015/02/06 职场文书
手术室护士个人总结
2015/02/13 职场文书
2015年纪念“卢沟桥事变”78周年活动方案
2015/05/06 职场文书
Python Pygame实战在打砖块游戏的实现
2022/03/17 Python