什么是Twisted

1.Twisted是一个基于Reactor模式的异步IO网络框架

首先说下什么是Reactor模式。Reactor模式就是利用循环体来等待事件发生,然后处理发生的事件的模式,如上图所示。

Reactor主要有如下两个功能:监视一系列与你I/O操作相关的文件描述符(description)。监视文件描述符的过程是异步的,也就是说整个循环体是非阻塞的;

不停地向你汇报那些准备好的I/O操作的文件描述符。

Twisted就是基于Reactor模式帮我们抽象出了异步编程模型以及各种非阻塞的io模块(tcp、http、ftp等),使我们很方便地进行异步编程。

2.Twisted程序我们将Twisted程序分为两个部分:我们写的代码和Twisted代码;

我们的代码与Twisted代码运行在同一个线程中;

当我们的代码运行时,Twisted代码是处于暂停状态的;

同样,当Twisted代码处于运行状态时,我们的代码处于暂停状态;

Reactor事件循环会在我们的回调函数返回后恢复运行。

在一个回调函数执行过程中,实际上Twisted的循环是被有效地阻塞在我们的代码上的。因此,我们应该确保回调函数不要浪费时间(尽快返回)。特别需要强调的是,我们应该尽量避免在回调函数中使用会阻塞I/O的函数。否则,我们将失去所有使用reactor所带来的优势。Twisted是不会采取特殊的预防措施来防止我们使用可阻塞的代码的,这需要我们自己来确保上面的情况不会发生。正如我们实际看到的一样,对于普通网络I/O的例子,由于我们让Twisted替我们完成了异步通信,因此我们无需担心上面的事情发生。

3.Twisted中的ReactorTwisted的Reactor只有通过调用reactor.run()才启动;

reactor循环是在其开始的线程中运行,也就是运行在主线程中;

一旦启动,reactor就会在程序的控制下(或者具体在一个启动它的线程的控制下)一直运行下去;

reactor空转时并不会消耗任何CPU的资源;

并不需要显式的创建reactor,只需要引入就OK了。

到这里是不是还感觉云里雾里的,不要紧,下面通过几个例子来更好的理解Twisted。

Twisted编程模型

1.阻塞和非阻塞客户端对比

开启诗歌服务器(开两个服务端口):

$ cd twisted-intro

$ python blocking-server/slowpoetry.py --port 10001 poetry/ecstasy.txt --num-bytes 300

$ python blocking-server/slowpoetry.py --port 10002 poetry/ecstasy.txt --num-bytes 300

使用阻塞版本客户端从两个服务端口下载诗歌:

$ python blocking-client/get-poetry.py 10001 10002

Task 1: get poetry from: 127.0.0.1:10001

Task 1: got 3083 bytes of poetry from 127.0.0.1:10001 in 0:00:07.710390

Task 2: get poetry from: 127.0.0.1:10002

Task 2: got 3083 bytes of poetry from 127.0.0.1:10002 in 0:00:07.710416

Got 2 poems in 0:00:15.420806

阻塞版本中Task 2得等到Task 1结束之后才能进行,总耗时15.4s。

使用twisted编写的异步版本客户端从两个服务端口下载诗歌:

$ python twisted-client-1/get-poetry.py 10001 10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 300 bytes of poetry from 127.0.0.1:10001

Task 2: got 300 bytes of poetry from 127.0.0.1:10002

Task 1: got 83 bytes of poetry from 127.0.0.1:10001

Task 2: got 83 bytes of poetry from 127.0.0.1:10002

Task 1 finished

Task 2 finished

Task 1: 3083 bytes of poetry

Task 2: 3083 bytes of poetry

Got 2 poems in 0:00:07.810432

twisted编写的异步版本中Task 1和Task 2是交替运行的,总耗时7.8s。

可以看到Twisted异步版本客户端比阻塞版本高效很多,原因是异步版本的io操作是非阻塞式的,遇到io等待时会先去处理其他任务。

2.Twisted低层接口编写的诗歌下载客户端程序

示例代码:twisted-intro/twisted-client-1/get-poetry.py

关键代码:reactor.addReader(reader):添加一个读取器;

需要实现一个reader,reader是一个读取器,需要遵守Twisted.internet.interfaces的IReadDescriptor接口规范,实现doRead、connectionLost、fileno三个方法;

doRead就是一个回调函数,当有socket准备就绪时被激活;

每当回调被激活,就轮到我们的代码将所有能够读的数据读回来然后非阻塞式的停止,如下图所示:

这种方式我们需要实现比较多的代码,比如需要实现底层socket通信(非阻塞)等。

3.Twisted高层接口编写的诗歌下载客户端程序

示例代码:twisted-intro/twisted-client-2/get-poetry.py

我们首先来看几个重要的类。

Transport:一个Twisted的Transport代表一个可以收发字节的单条连接。

Protocol:Twisted的Protocol抽象由interfaces模块中的IProtocol定义。Protocol定义了数据传输的协议,如TCP、FTP、IMAP或其他我们自己制定的协议;

Protocol实例如何得知它为哪条连接服务呢?如果你阅读IProtocol定义会发现一个makeConnection函数。这是一个回调函数,Twisted会在调用它时传递给其一个也是仅有的一个参数,即Transport实例。这个Transport实例就代表Protocol将要使用的连接。

Protocol Factory:一个连接对应一个Protocol实例,Protocol Factory会为每一个连接创建一个Protocol实例;

Protocol Factory的API由IProtocolFactory来定义,同样在interfaces模块中。Protocol Factory就是Factory模式的一个具体实现。buildProtocol方法在每次被调用时返回一个新Protocol实例,它就是Twisted用来为新连接创建新Protocol实例的方法;

在Protocol Factory中还可以定义回调函数,在某个事件发生时调用。

几个类的关系图如下:

再来看看get-poetry.py的程序逻辑:首先调用reactor的connectTCP方法,将服务器的ip、port以及Protocol Factory对象传入该方法;

然后Twisted会调用Protocol Factory实例的buidProtocol方法创建Protocol实例,并使Protocol和Factory关联,逻辑图如下:Twisted调用Protocol实例的makeConnection与transport联系起来:Protocol调用dataReceived回调接收Transport传过来的数据。

Twisted高层接口帮我们屏蔽了很多底层的实现,让我们更多的关注业务逻辑。实际的dataReceived回调过程应该是这样:

4.更加抽象的运用Twisted

示例代码: twisted-intro/twisted-client-3/get-poetry.py

此示例和twisted-client-2/get-poetry.py版本的代码不同就是从Protocol factory中把回调函数抽象出来,使Protocol Factory代码可以被复用:

# coding:utf-8

# 示例:异步从诗歌服务器下载诗歌

from twisted.internet import reactor

from twisted.internet.protocol import Protocol, ClientFactory

class PoetryProtocol(Protocol):

"""定义数据传输协议"""

poem = ''

def dataReceived(self, data): # 接收数据

self.poem += data

def connectionLost(self, reason): # 当断开连接时执行

self.poemReceived(self.poem)

def poemReceived(self, poem):

self.factory.poem_finished(poem) # f执行factory类的poem_finished方法

class PoetryClientFactory(ClientFactory): # ClientFactory的buildProtocol方法,会实例化protocol类

"""1.指定protocol类,既告诉twisted用什么样的规则处理TCP数据流2.定义用户的回调和错误回调"""

protocol = PoetryProtocol # 指定protocol类

def __init__(self, callback, errback):

self.callback = callback

self.errback = errback

def poem_finished(self, poem):

self.callback(poem)

def clientConnectionFailed(self, connector, reason): # 当连接失败时调用错误回调

self.errback(reason)

def got_poem(poem): # 回调

poems.append(poem)

poem_done()

def poem_failed(err): # 错误回调

print >>sys.stderr, 'Poem failed:', err

errors.append(err)

poem_done()

def poem_done():

if len(poems) + len(errors) == len(addresses):

reactor.stop()

poems = []

errors = []

factory = PoetryClientFactory(got_poem, poem_failed)

reactor.connectTCP(host, port, factory)

reactor.run() # 启动事件循环

for poem in poems:

print(poem)

程序运行过程如下图所示:

总结:编写Twisted程序时,脑海中一定要有一个循环体,且将循环体分成两部分:我们的代码和Twisted代码;

Twisted代码:有各种写好的非阻塞网络模块,循环监听返回内容,一旦收到返回内容则调用回调函数,执行我们的业务逻辑;

我们的代码:各种回调函数,处理socket数据流;

整个循环体是单线程的,所以我们写的回调一定要是非阻塞的,否则就失去了异步的优势了。如果回调函数有io操作,那么需要将此回调异步化,下一篇内容会讲到。

python twisted是什么_Twisted基础介绍(一)相关推荐

  1. python exceptions怎么用_Python基础介绍 | Exceptions异常

    想到本科时候学的Java,各种思想思路,但就是实践得少了,所以讲了也生疏,但让自己静静地敲一敲,你也就明白程序语言里没啥新鲜事. 今天来讲讲程序中的异常: 出现问题时会引发异常.例如,如果你尝试除以零 ...

  2. python twisted教程_twisted基础教程.pdf

    twisted基础教程 Twisted 网络编程必备(一) 0.1 为什么使用Twisted? 如果你并不准备使用Twisted,你可能有很多异议.为什么使用Twisted 而不是其他网络函数 库或框 ...

  3. Python Twisted 介绍

    Python Twisted介绍:http://blog.csdn.net/hanhuili/article/details/9389433 原文链接:http://www.aosabook.org/ ...

  4. Python Twisted介绍

    原文链接:http://www.aosabook.org/en/twisted.html 作者:Jessica McKellar Twisted是用Python实现的基于事件驱动的网络引擎框架.Twi ...

  5. Python基础介绍

    本节内容 Python介绍 发展史 Python 2 or 3? 安装 Hello World程序 变量 用户输入 模块初识 .pyc是个什么鬼? 数据类型初识 数据运算 表达式if ...else语 ...

  6. python介绍和用途-Python基础介绍(一)

    Python基础介绍(一) 1. python是什么编程语言 编译型与解释型 ​编译器吧源程序的每一条语句都编译成机器语言,并保存成二进制文件,这样运行时计算机可以直接以极其语言来运行此程序,速度很快 ...

  7. 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍 一、pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主

    利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍 一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目 ...

  8. python最基本的规则是什么_Python基础介绍(一)

    Python基础介绍(一) 1. python是什么编程语言 编译型与解释型 ​编译器吧源程序的每一条语句都编译成机器语言,并保存成二进制文件,这样运行时计算机可以直接以极其语言来运行此程序,速度很快 ...

  9. python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式

    本文实例讲述了Flask框架学习笔记之表单基础介绍与表单提交方式.分享给大家供大家参考,具体如下: 表单介绍 表单是HTML页面中负责数据采集功能的部件.由表单标签,表单域和表单按钮组成.通过表单,将 ...

最新文章

  1. vim 初学简单设置
  2. python【力扣LeetCode算法题库】104-二叉树的最大深度
  3. Google Drive的linux客户端使用(还没弄完)
  4. 用imageMagick的composite合并图片
  5. 基于 Docker 打造前端持续集成开发环境
  6. 修改小程序swiper 点的样式_高质量的微信小程序样式模板应该长什么样?
  7. 在Microsoft System Center中利用您的现有投资管理VMware--Veeam MP v6.5
  8. 【java】java 扩展可回调的Future
  9. 服务器虚拟化平台 可信云认证,100%满足规范,华为云Stack首批通过可信云虚拟化云平台最高等级认证...
  10. js复制操作,复制成功弹出提示框
  11. 计算机辅助设计与制造实例教程答案,计算机辅助设计实例教程= Example Course of Computer Aided Design...
  12. 颜色代码查询,在线颜色选择器,RGB颜色对照表
  13. Java-如何防范CSRF攻击
  14. CleanMyMac X 4.8版本更新!
  15. Deep Learning Algorithm for Cyberbullying Detection
  16. PicoNeo3开发VR项目
  17. linux离线安装jemalloc,jemalloc在linux上从安装到使用
  18. EXT.JS 学习笔记
  19. Android iText向pdf模板插入数据和图片
  20. 免费java视频教程大全在线观看

热门文章

  1. Unity强化学习工具MLAgents
  2. dw虚拟服务器,dw设置服务器
  3. 使用伟福仿真器对IAR 8051生成的HEX文件进行仿真
  4. Python中format函数用法
  5. Linux常用命令——time命令
  6. 二级联动省市mysql数据库_「zxfy」jQuery+php+mysql,轻松实现ajax无刷新省市二级联动 - seo实验室...
  7. 关于vue的seo优化
  8. 最小生成树-Prim算法和Kruskal算法
  9. MySql重装失败解决办法
  10. ASCII码表及其扩展