Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5096615
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2011-11-23 12:02:11

其他许多文档都是致力于定义Twisted。如果现在你能猜出我写此书的意图,你就知道我不仅试着解释Twisted是什么,而且说明它应该是什么。

首先,Twisted很有趣。它起源于一款游戏,并在游戏中用于商业活动中,它将会,并且我个人也希望它能给用户带来entertaining的交互的用户体验。

Twisted对网络应用开发者来说是一个平台。Python语言本身就很强大,但它缺少很多其他语言都在极力添加的功能。现在好了,Twisted是一款很好的(稍微特别的)纯python框架或库,这取决于你如何看待它,并且它不断的在完善。

作为一种平台,Twisted应专注于集成。理想情况下,所有功能都能通过任何协议访问;至少,这些功能应该通过至少一种协议,使用适当统一的用户接口来进行配置。Twisted开发的下一个阶段会致力于配置系统上,该系统将统一当前很多完全不相干的基础框架,并且非程序员也能让它们附加在一起工作。

的高级特性概述
异步编程

该文档介绍异步变成模型,Twisted延迟抽象,该延迟抽象就是一个“承诺”的结果,而且会传递一个最终发生的结果给处理函数。

对于熟悉Python语言,并且至少对网络核心概念如服务端,客户端,socket有认识的人来说,关于Twisted的文档中该文档还是比较新的。该文档将概述并发程序设计(interleaving多个任务)和Twisted的并发模型:非模块化代码或异步代码。

Defferred对象时候处理结果的方法。[J1] 

并发程序设计介绍

很多计算型的任务会花费很长时间完成,两个原因可能使任务花费这些时间:

1.    密集计算(如大数据的因数分解),需要相当多CPU时间来计算结果;

2.    非密集计算,但不得不等待有效的数据来产生结果。

等待回复

网络编程的一个重要特点就是等待数据。设想,你有一个函数,用于发送包含一些概要性信息的邮件。该函数需要连接到远程服务器,等待远程服务器的响应,然后检测远程服务器能否处理邮件,然后再等待回复,之后发送邮件,再等待确认,最后断开连接。

任何一个环节都有可能花费很长的时间,[J2] 。但这种情况下,有明显的、根本的局限性:它不能同时发送多封邮件;事实上它除了发送一封邮件外,其他任何事情都不能做。

从此刻起,除了最简单的网络编程外都要避免这种模型。你可以使用多个不同模型中的一种,让你的程序在某些任务继续之前处于等待状态时,能继续处理手头上的其他任何任务。

拒绝等待数据

有很多编写网络程序的方法,例如:

1.      每个连接在不同的操作系统进程中处理,这种情况下,操作系统就要注意一个进程在等待,而其他都在运行的情况;

2.      每个连接在不同的线程中处理①,这种情况,线程框架就要考虑一个线程在等待,而其他都在运行的情况;

3.      使用非阻塞系统调用,在同一个线程中处理所有连接。

非模块化调用

使用Twisted框架时,标准的模型是第三种模型:非阻塞调用。

当在一个线程中处理多个连接时,调度是应用程序的责任,而不是操作系统的,当每个连接准备读或写时,它通常通过调用一个已登记的函数来实现——通常被称之为异步,事件驱动,或基于回调机制的编程方式。

该模型中,之前发生邮件的功能就像:

1.    调用一个连接函数,连接远程服务器;

2.    连接函数立即返回,同时当连接被建立时,邮件发送程序就会被调用;

3.    一旦连接建立,连接装置就会通知邮件发送函数连接已经建立。

以上的序列与之前的阻塞序列有什么优点?优点就是邮件发送函数在连接打开之前不能做下面一部分工作的时候,其他程序可以做其他任务, [J3] 。从此,整个程序就不再等待连接了

回发

经典异步模型在通知应用程序数据有效时,是通过回调通知的。应用程序调用函数请求数据,请求还传递了一个回调函数,该函数会在数据有效时被调用,并将数据作为一个参数传递给回调函数。[J4] 

同步编程方式是:函数请求数据,等待数据,处理数据。异步编程则是:请求数据,当数据有效时,调用回调函数。

延迟对象Deferreds

Twisted使用Deferred对象来管理回调序列。客户端应用程序将一系列的函数附加到Deferred对象中,以便当异步请求的结果有效时候被调用(该系列函数被称之为回调序列或回调链);如果在异步请求中出现错误也将被调用(此时被称之为错误回调或错误回调链)。当结果有效时,异步代码第一次调用回调函数,或者发生错误时,第一次调用错误回调函数,Defferred对象会将每个回调函数或错误回调函数的结果传递给链上的下一个函数。

解决方案

第二种并发问题——非密集计算任务,它涉及明显的延迟——Deferreds旨在帮助解决该问题。硬盘访问、数据库访问和网络访问的延迟功能都要使用该类,尽管延迟时间各不相同。

Deferred旨在使Twisted程序等待数据,而不要在数据到达之前处于挂起状态。它们通过为回调给程序和应用程序的函数提供简单管理接口来实现。程序始终知道通过调用Deferred.callback来使得结果有效或发生错误时调用Deferred.errback。应用程序根据他们希望被调用的次序,来附加回调函数和错误回调函数来设置结果处理。

Deferred的基本思想及解决问题的方案,就是尽量保持CPU处于活动状态。如果一个任务正在等待数据,宁可CPU(和程序)空闲着也还在等待数据(称之为“阻塞”的过程)的话,这时程序就可以执行其他操作,当等到一些数据有效的信号后,再返回到原进程。

Twisted中,函数发送信号给调用函数,说明自己正在等待返回Deferred对象。当数据有效时,Deferred上的回调函数来处理数据。[J5] 

 

数据到达的信号

在前面发生邮件的示例中,主函数调用一个函数连接远程服务器。异步不要求连接函数立即返回结果,好让主函数能做其他的工作。那么主函数或其控制程序是如何知道连接还不存在的呢?连接一旦存在又是如何使用的呢?

Twisted针对该情况有一个信号对象。当连接函数返回时,返回一个twisted.internet.defer.Deferred对象作为操作没有完成的信号。

Deferred有两个目的。一是表示“我是一个信号,表示你让我做的事还没有结果”。二是当数据有效时,你可以要求Deferred做一些工作。

回调函数

一旦数据有效,你要告诉Deferred如何处理数据的方法是添加回调函数——数据有效时就让Deferred调用该函数。

一个返回Deferred对象的Twisted库函数是twisted.web.client.getPage。下面的示例中,我们调用getPage函数,它返回一个Deferred对象,我们将附加一个回调函数,在数据有效时候用来处理页面的内容:

 

  1. from twisted.web.client import getPage
  2. from twisted.internet import reactor

  3. def printContents(contents):

  4. '''
  5. This is the ’callback’ function, added to the Deferred and called by
  6. it when the promised data is available
  7. '''

  8. print "The Deferred has called printContents with the following contents:"

  9. print contents

  10. # Stop the Twisted event handling system -- this is usually handled
  11. # in higher level ways

  12. reactor.stop()

  13. # call getPage, which returns immediately with a Deferred, promising to
  14. # pass the page contents onto our callbacks when the contents are available

  15. deferred = getPage(’http://twistedmatrix.com/)

  16. # add a callback to the deferred -- request that it run printContents when
  17. # the page content has been downloaded

  18. deferred.addCallback(printContents)

  19. # Begin the Twisted event handling system to manage the process -- again this
  20. # isn’t the usual way to do this

  21. reactor.run()

Deferred对象最普遍的用法就是附加两个回调函数,第一个回调函数的处理结果将作为参数传递给第二个回调函数:

 

  1. from twisted.web.client import getPage
  2. from twisted.internet import reactor

  3. def lowerCaseContents(contents):

  4. '''
  5. This is a ’callback’ function, added to the Deferred and called by
  6. it when the promised data is available. It converts all the data to
  7. lower case
  8. '''

  9. return contents.lower()

  10. def printContents(contents):

  11. '''
  12. This a ’callback’ function, added to the Deferred after lowerCaseContents
  13. and called by it with the results of lowerCaseContents
  14. '''

  15. print contents
  16. reactor.stop()
  17. deferred = getPage(’http://twistedmatrix.com/)

  18. # add two callbacks to the deferred -- request that it run lowerCaseContents
  19. # when the page content has been downloaded, and then run printContents with
  20. # the result of lowerCaseContents

  21. deferred.addCallback(lowerCaseContents)
  22. deferred.addCallback(printContents)
  23. reactor.run()
错误处理:错误回调函数

正如在得出结果之前异步函数就返回了,也有可能是出现了一些错误而返回的,如连接失败、错误的数据、协议错误等等。正如你添加回调函数到Deferred,由它在预期的数据有效时调用,你同样可以添加错误处理函数(错误回调函数)到Deferred,由它在发生错误或得不到数据时调用:

 

  1. from twisted.web.client import getPage
  2. from twisted.internet import reactor
  3. def errorHandler(error):
  4. ’’’
  5. This is an ’errback’ function, added to the Deferred which will call
  6. it in the event of an error
  7. ’’’
  8. # this isn’t a very effective handling of the error, we just print it out:
  9. print "An error has occurred: <%%s%>" % str(error)
  10. # and then we stop the entire process:
  11. reactor.stop()
  12. def printContents(contents):
  13. ’’’
  14. This a ’callback’ function, added to the Deferred and called by it with
  15. the page content
  16. ’’’
  17. print contents
  18. reactor.stop()
  19. # We request a page which doesn’t exist in order to demonstrate the
  20. # error chain
  21. deferred = getPage(’http://twistedmatrix.com/does-not-exist’)
  22. # add the callback to the Deferred to handle the page content
  23. deferred.addCallback(printContents)
  24. # add the errback to the Deferred to handle any errors
  25. deferred.addErrback(errorHandler)
  26. reactor.run()
 
结论

这份文档中,你会:

1.    发现为什么无所不能的网络程序需要拥有并发机制;

2.    学到Twisted框架支持在异步调用机制中的并发;

3.    学到Twisted框架拥有管理回调链的Deferred对象;

4.    发现getPage函数如何返回Deferred对象的;

5.    附加回调函数和错误回调函数到Deferred;及

6.    发现Deferred的回调链及错误回调链的使用。

 

参考

由于Deferred抽象在Twisted编程中是如此核心的部分,这里有其他几个关于它的详细指南:

1.    Using Deferreds (page 102), 更完整的Deferred应用指南,包括Deferred链。

2.    Generating Deferreds (page 111), 关于创建Deferred、使用回调链的指南。

 

概述

Twisted网络是一个可兼容的Python事件循环的集合。它控制代码将事件发送给感兴趣的观察者和可移动的API,使得观察者不必理会哪个事件循环在运行。因此,不同的循环使用相同的代码是完全可能的。从基本的Twisted,甚至移动设备中选择基本的循环用到各种GUI工具的循环中,如GTK+Tk

Twisted网络包含各种反应器API的接口,它们的用法在文档的低级Twisted章节。这些API分别是IReactorCore,IReactorTCP,IReactorSSL,IReactorUNIX,IReactorUDP,IReactorTime,IReactorProcess,IReactorMulticastIReactorThreads。反应器API运行做出非持久性的调用。

Twisted还涵盖了各种传输接口,包括ITransport及其先关。这些接口使得编写Twsited网络代码免于考虑底层传输的实现。

IProtocolFactory接口制定了工厂的规范,它通常是第三方库中很大一部分内容。

 

阅读(1562) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~