Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5119207
  • 博文数量: 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

2015-04-10 22:46:03

第五章
强调了学习twisted的要记住:
大多数的higher-level abstraction是建立在使用lower-level abstraction之上,而不是替代它们。所以在学习的时候,要记住什么是它做的和不做的事情。
目前为止学到的最重要的abstraction是reactor,没有其他任何的abstraction可以提供reactor提供的功能。所以,twisted的其他部分,都可以看作是:更将容易的使用reactor完成某件事情的东西。
使用更高层级的abstraction意味着写更少的代码,并且让twisted来处理跨平台的东西。

介绍了比第四章更加高层次的几个abstraction:Transports,Protocols,Protocol Factories。
Transport:代表了一个可以接受/发送(或者都可以)数据的链接
Protocol:实现了一个指定的网络协议,如FTP和IMAP或者自定义的协议
Protocol Factories: 负责创建Protocol instance。因为我们让twisted来建立链接,所以twisted需要一个途径,无论何时一个新的链接被建立,都可以制造一个合适的Protocol。 

第六章
在第五章的例子的基础上,改写的更加re-usable: 通过一系列的callback(callback chains),最终调用了业务逻辑的代码
从而引出一个重要的观点:使用twisted,就是用一系列的由reactor支持的asynchronous callback chain 调用来构建自己的程序。twisted的所有API都必须是异步的,异步和同步的代码不可以混在一起。
另外,介绍了异步的程序中,如何使用callback来处理错误:把原来的callback分开两个,一个处理正常的情况,一个处理错误出现的情况。但这并不意味着每一个函数都必须包含callback和error callback两个参数, twisted有相应的abstraction。

第七章
介绍了Deferred,用来更加容易的用callback来编程。Deferred内在的包含了两条callback chain,一条处理正常情况,一条处理错误情况,可以往callback chain里面添加callback;根据正确或者错误的情况,可以fire相应的callback chain,称作fire the chain,这个chain里面的callback就会按照添加的顺序被条用,并且保证只调用一次,避免了由于多次调用callback、错误调用callback可能会引起难以查找的bug,提供类似同步编程里面try/except语句提供的机制。另外,Deferred可以是我们更加容易的重构代码:往Deffered的callback chain里面添加link,或者将代码从一个link转移到另外一个。

第八章
用deferred来改写前面的程序例子,讲解了使用deferred的容易陷入的误区。
Deferred是一个用来管理callback的解决方案,而不是用来避免使用callback,也不是用来把block callbacking 变成non-blocking callback。
返回一个deferred是twisted 的异步API和用twisted来编写的程序一个典型的做法,这样引出了deferred的概念:一个Deferred object代表了一个异步的结果,或者是一个还没有完全完成的结果。程序功过返回一个deferred,来告诉使用者“我是异步的”,并且提供一个机制(添加callbacks 和 error callbacks),当结果到达的时候,让使用者得到这个结果。

deferred firing pattern(Deffered里面callback和errbacks的调用顺序):
1、一个Deffered包含了一个排序好的callback/errback pairs 链,这个顺序就是它们被添加的顺序。
2、在步骤0(第一步),当defferred 由callback method fire 的,那么步骤0的callback会被调用;
如果是由errback method fire 的,那么步骤0的callback会被调用。
3、如果第N步失败了,那么第N+1的errback会被调用(with exception wrapped in a Failue),
如果成功了,则第N+1的callback会被调用(with the stage N return value as the first argument.)


第十章
介绍了如何使用Deffered来route errors and result down the chain,用例子来说明了deffered里面的控制流如何在callback和errback之间来回的转换,取决于每一步返回的结果:如果返回的是exception(wrap by Failue)的去到下一步的errback,否则则去到callback。

第十一章
用twisted来实现一个简单的server。
首先,调用listenTCP告诉Twisted创建一个listening socket并把这个socket添加到event loop中。listening socket上的一个event并不意味着有可读的数据,而是意味着有个client在等待着连接上server。 
Twisted会自动的接受connection request,然后创建一个新的client socket,这个socket就是连接server和一个独立的client的,它同样的被添加到event loop上面,然后Twisted创建一个新的Transport 安定一个新的Protocol实例(通过ProtocolFactory)用以为这个指定的client服务。所以Protocol实例总是连接到client socket,而不是listening socket。

第十二章
1、介绍了双向通信:client向server发送数据,然后server返回一个经过转换的数据给client,使用同一种protocol。
2、如何在twisted提供的现成的implementation上建立自己的代码。
3、使用service object来分隔功能性逻辑 和 protocol逻辑。

第十三章
介绍了在一个deffer的callback chain 里面,如果其中的callback(或errback) 函数返回值是deffered,会是怎样处理的:外城的deffer会等待内层deffer直到内层deffer被fired。等待并不是block,而是外层deffered的callback chain的执行被挂起,然后把控制权返回给reactor(或者是其他fire外层deffed的东西)

第十四章
deffer 在 fired之后还可以再添加callback 和errback,此时一添加就马上执行。
deffer在fired之后,调用pause() 函数,再添加callback或者errback,不会马上执行,直到uppause() 了之后,才会马上执行。
所以我们可以在返回一个deffer之前fire它:
1、用maybeDefferred() 来处理一个有时候返回deffered有时候返回一个正常值(或者抛异常)的函数。
2、用deffer.successd() 或者defer.fail() 用来预先fire一个defferd,这样我们自己写的“半同步”的函数就总是返回一个deffer。
deffer其实跟internet没有任何关联,只是用来管理callback的一个抽象。

第十五章
介绍了twisted自带的测试框架trial,它可以用来调试异步的代码。
setUp() 和tearDown() 是可选的,用来做测试之前的准备工作和测试完成之后的后续工作。
每一个test case 都是一个以test_ 开头的函数,如果test_xx() 函数返回的是一个deffered,就意味着这
这个test case 是一个异步的函数。setUp(), tearDown 也可以返回deffered。
在trial里面,每一个test method 都是作为一个callback来运行的,也就是意味着reactor在运行,并且
我们可以在test里面进行一些异步的操作。
想知道更多的unit test的例子,最好的途径就是看Twisted本身的代码,Twisted本身自带很大量的unit test
,因为这些都是开发twisted 的专家写的,所以很好的展示了如何正确的测试twisted代码。

第十六章
介绍了如何将前面的server产品化、daemonlogie化(按我的理解就是自己可以在后台长期平稳运行,不需要terminal、人工干预)
1、作为daemon process运行
2、将调试信息和出错信息发送到 rotated log files ,或是syslog service
3、去掉过多的权限
4、将daemon process的pid记录在一个文件年里面,这样系统管理员可以很容易的向daemon发送信号。
两个新的概念:
IService Interface: 定义了一个named service ,可以使这个service开始和停止。service 所做的就是提供了一些通用的属性和方法。
两个必须的属性:name 和 running。name是string或者为None,runing 是一个布尔值,为True表示这个service 已经成功的开始了。
两个重要的方法:startService和stopService。
stopService可能会返回一个deffered,这样的deffered应该在service完全关闭的时候被fire,这样可以让我们的service 在整个应用结束之前完成清理手尾的工作。如果返回None, service就会马上关闭。
IServiceCollection Interface:多个service可以被放在一起形成一个collection,在collection里面的所有service同时开始和停止。 IService 的setServiceParent, 可以将一个Service添加到一个colection。 service可以有parent,也就是意味着它们可以形成层级。这就带出了IServiceCollection的概念:定义了一个可以包含多个IService object的object。提供了getServinceNamed(根据name来查找一个service);遍历里面所有的service__iter__), addService(添加一个service到collection),removeService
Application Interface: 实际不是单独定义的一个interface,一个Application oject必须同时实现IService和IServiceCollection,初次之外,还一些其他的interface(本章没有涉及到)。一个Application 是整个twisted 应用的最高层的service,其他的所有Daemon里面的service都是它的子孙。一般不需要自己实现Application,twisted提供现成的实现,可以直接使用。
twisted loggin:twisted 提供了自己的日志结构。
twisted 的tac file: 就是twisted的环境配置文件,代表了一个特定的布局,记录的是例如端口号、文件路径等信息。
twisted plugin system:tac file 让我们在配置server的时候有很大的灵活性,但有时候我们并不需要这么多的灵活性,有时候可配置的选项很少,为每一种配置都弄一个tac file显得太麻烦了,如果可以在twisted 命令行直接指定这些选项就很方便,twisted的plugin 系统就提供了这样的可能。
IPlugin Interface: 实际上,这个interace没有指定任何方法,实现IPlugin只是意味着这是一个plugin,让twisted可以找到它。当然,要让plugin 有实际用处,它还必须实现其他的interface。
IServiceMaker interface:一个实现了IServiceMake的object知道如何创建一个IService。 


第十八章
有时候,我们需要并行的运行一组异步的操作,因为twisted 是单线程的,所以它们不会真正的并行,重点是
我们需要在同一个组多个任务中使用异步I/O来尽可能快的工作,那么我们怎么知道所有已经开始的一部操作都
已经完成了呢?twisted提供了这样的一中抽象,用来帮助解决这个问题: The Deffered List。
一个DefferedList 是从一个python list创建的,这个python list 里面的每一个元素必须是Deffered Object。
DefferedList 本身也是一个deffered(它继承自Deffered), 这意味着你可以添加callback和errback,就像
普通的deffered一样。
如果用来构建DefferedList的list是空的,那么Deffered的callback会在被添加的时候马上被fired。
deffered list 的结果也是一个list,list 里面的每个元素是一个2元素的tuple: (is_success, res)
is_success:布尔量, res 是deffered list 里面的deffered 的结果;返回的list里面,结果的顺序跟
deffered list 里面deffered 的顺序是对应的。
如果DefferedList里面的deffered 不为空,那么在所有的deffered都被fired之后,它自身才会被fired,
也就是说这是它的callback/errback才会被调用。如果为空,那么DefferedList会被马上fired,因为
它不用等待任何的deffered被fired。
DefferedList永远不会fail,因为deffered list里面所有的result 都会被收集(不管是result还是Failure)
DefferedList的构造函数中,consumeErrors参数的作用:DefferedList需要知道它里面的每一个deffered
何时被fire,它通过通过在每个deffered里面添加一个callback和errback来做到。默认的情况,callback
和errback都是返回原来的result/failure的。所以,如果某个deffered的最后一步失败了,并且返回的是
一个failue并且作为DefferedList添加的这个errback的参数,而这个errback前面说过了,它只是简单的返回
自己接收到的这个failue,所以就出现了一个没有被处理的failue,会报错。如果把comsumeError设置为
True,那么DefferList添加的这个errback会返回一个None,这样相当是把接收到的failure comsume 了。


第十七章:
介绍了除了defer之外,另外一种组织和管理callback的方法:inlineCallbacks
1、inlineCallbacks 是一个decorator,它可以把一个generator函数(使用了yield语句的函数)变成是一系列的异步callbacks的调用。
2、调用decoratored by inlineCallbacks 的函数的时候,我们不需要调用send、next等函数把yield的结果发送给generator,inlineCallbacks负责这一切,保证generator可以顺利跑完(前提是generator本身不抛异常)
3、如果yield的是defer,那么generator会暂停,直到返回的defer被fired。如果defer是success的,则返回defer的结果,否则,就抛异常(普通的Exception,而不是Failue)
@inlineCallbacks
def some_func():
res1 = yield ...
res2 = yield ..
defer.returnValue(res2)

d = some_func()
d.addCallback(func1)
d.addBoth(func2)

经过inlineCallBacks的修饰,some_funct() 返回的是一个deffer,调用者只需要往这个defer添加callback/errback, 剩下的事情就由inlineCallBacks和some_func来协调完成。注意,返回的defer并不是yield 的defer,这个返回的defer仅当generator运行完或者抛一个异常的时候,才会被fired。
some_func里面有三种跟inlineCallBacks会产生互动的语句:
1、yield some_expr 
如果yield 的是common value(就是不是defer),那么会直接返回给yield左边的表达式,a = yield b 相当于 a = b; 如果yield的是defer,那么inlineCallback会保证yield 表达式的值(如res1 )会得到defer被fired的时候的结果(res or err)
2、defer.returnVale(some_val)
实际上是带着some_val 的异常,这个异常被inlineCallbacks捕捉,然后some_val作为defer的结果用来fired 这个difer:defer.callback(some_value)
3、最后没有使用returnValue() 来返回值,到了some_func执行完
inlineCallback会捕获一个StopIteration(表示一个generator执行到了the end of function),此时对于some_func来说,是没有值返回的,所以在inlineCallbacks里面,就会调用deffer.callback(None),然后返回defer。
4、抛其他的异常
inlineCallbacks会调用deffer.errback()
让some_func从头跑到尾的前提是:some_func本身不抛异常

使用inlineCallbacks的好处:
1、所有的callbacks都共享一个namespace,所以不用传递额外的状态
2、callback的顺序很容易看得出,就是从上到下
3、节省打字:不用定义独立的callback function,隐含了的flow-control
4、错误处理可以用熟悉的try/except 语句
缺点:
generator里面的callbacks不能单独的被调用,造成了代码不易重用
看起来像同步编程的形式容易让实际是异步的function 在被调用的事实被隐藏起来。


原文链接
阅读(1724) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~