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实现文件路径和url相互转换的方法
Jul 06 Python
python面向对象_详谈类的继承与方法的重载
Jun 07 Python
Python 查找字符在字符串中的位置实例
May 02 Python
python+selenium打印当前页面的titl和url方法
Jun 22 Python
使用python将请求的requests headers参数格式化方法
Jan 02 Python
python 实现矩阵按对角线打印
Nov 29 Python
Django模板标签中url使用详解(url跳转到指定页面)
Mar 19 Python
PyQt5结合matplotlib绘图的实现示例
Sep 15 Python
python 爬虫基本使用——统计杭电oj题目正确率并排序
Oct 26 Python
全面介绍python中很常用的单元测试框架unitest
Dec 14 Python
Python使用paramiko连接远程服务器执行Shell命令的实现
Mar 04 Python
python 如何执行控制台命令与操作剪切板
May 20 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
Windows下PHP5和Apache的安装与配置
2006/09/05 PHP
php下清空字符串中的HTML标签的代码
2010/09/06 PHP
PHP数组循环操作详细介绍 附实例代码
2013/02/03 PHP
Symfony2实现在doctrine中内置数据的方法
2016/02/05 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
2019/04/02 PHP
jquery如何根据值设置默认的选中项
2014/03/17 Javascript
jquery获取html元素的绝对位置和相对位置的方法
2014/06/20 Javascript
jQuery读取XML文件内容的方法
2015/03/09 Javascript
原生js实现下拉框功能(支持键盘事件)
2017/01/13 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
Angular中$state.go页面跳转并传递参数的方法
2017/05/09 Javascript
微信小程序-getUserInfo回调的实例详解
2017/10/27 Javascript
jQuery实现滚动效果
2017/11/17 jQuery
JS实现DOM删除节点操作示例
2018/04/04 Javascript
Angular6 用户自定义标签开发的实现方法
2019/01/08 Javascript
vue简单练习 桌面时钟的实现代码实例
2019/09/19 Javascript
JS实现网站吸顶条
2020/01/08 Javascript
js实现简单放大镜效果
2020/03/07 Javascript
[53:10]完美世界DOTA2联赛决赛日 FTD vs GXR 第二场 11.08
2020/11/11 DOTA
python函数参数*args**kwargs用法实例
2013/12/04 Python
python矩阵转换为一维数组的实例
2018/06/05 Python
快速解决vue.js 模板和jinja 模板冲突的问题
2019/07/26 Python
Python通过Manager方式实现多个无关联进程共享数据的实现
2019/11/07 Python
对tensorflow中的strides参数使用详解
2020/01/04 Python
pytorch的梯度计算以及backward方法详解
2020/01/10 Python
美国排名第一的葡萄酒俱乐部:Firstleaf Wine Club
2020/01/02 全球购物
小学节能减排倡议书
2014/05/15 职场文书
测绘工程专业求职信
2014/07/15 职场文书
2014年质检工作总结
2014/11/26 职场文书
2014年酒店年度工作总结
2014/12/10 职场文书
质检员岗位职责范本
2015/04/07 职场文书
结婚堵门保证书
2015/05/08 职场文书
会议营销主持词
2015/07/03 职场文书
护理自荐信
2019/05/14 职场文书
Python基础之元编程知识总结
2021/05/23 Python
浅谈如何保证Mysql主从一致
2022/03/13 MySQL