Chinaunix首页 | 论坛 | 博客
  • 博客访问: 284430
  • 博文数量: 40
  • 博客积分: 1807
  • 博客等级: 上尉
  • 技术积分: 350
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-03 15:42
文章分类

全部博文(40)

文章存档

2011年(18)

2010年(20)

2009年(2)

我的朋友

分类: Python/Ruby

2011-01-20 22:48:10

先简单说一下python decorator:
  1. @A
  2. def f ():
  3.     …

  4. 这种形式是decorator不带参数的写法。最终 Python 会处理为:

  5. f = A(f)

如此这样,

  1. from twisted.internet import defer
  2. from twisted.web import client
  3. from twisted.internet import reactor
  4. import sys

  5. @defer.inlineCallbacks
  6. def enqueueTaskToDisplayURL(url):
  7.     try:
  8.         data = yield client.getPage(url)
  9.         print data
  10.     except Exception, e:
  11.         print >> sys.stderr, "Error:", e
  12.         return;
  13.     finally: reactor.stop()

  14. if __name__ == "__main__":
  15.     enqueueTaskToDisplayURL("")
  16.     reactor.run()

enqueueTaskToDisplayURL = defer.inlineCallbacks(enqueueTaskToDisplayURL)

把enqueueTaskToDisplayURL当做了一个callback函数。谁的callback呢?

我们注意到enqueueTaskToDisplayURL同时它又是一个generator,执行到第一个yeild的时候,便会返回yeild后异步函数的defer对象。则callback就add到了该defer对象。

当getPage的数据ready的时候,generator通过send(data)返回数据。generator便从第一个yield后开始执行。

总结:

1)通过@defer.inlineCallbacks + yield, 帮助程序员将异步的代码写成了同步的方式。

2)Twisted's @inlineCallbacks decorator basically does this for you; whenever you yield a deferred (Twisted's representation of an ongoing operation), the rest of the generator is registered as the callback for when the operation is finished.

------------------------------------我是分割线----------------------------------------------

摘一下从twistedmatrix.com上搞的document:

inlineCallbacks helps you write Deferred-using code that looks like a regular sequential function. This function uses features of Python 2.5 generators. If you need to be compatible with Python 2.4 or before, use the deferredGenerator function instead, which accomplishes the same thing, but with somewhat more boilerplate. For example:

@inlineCallBacks def thingummy(): thing = yield makeSomeRequestResultingInDeferred() print thing #the result! hoorj!

When you call anything that results in a Deferred, you can simply yield it; your generator will automatically be resumed when the Deferred's result is available. The generator will be sent the result of the Deferred with the 'send' method on generators, or if the result was a failure, 'throw'.

Your inlineCallbacks-enabled generator will return a Deferred object, which will result in the return value of the generator (or will fail with a failure object if your generator raises an unhandled exception). Note that you can't use return result to return a value; use returnValue(result) instead. Falling off the end of the generator, or simply using return will cause the Deferred to have a result of None.

The Deferred returned from your deferred generator may errback if your generator raised an exception:

@inlineCallbacks def thingummy(): thing = yield makeSomeRequestResultingInDeferred() if thing == 'I love Twisted': # will become the result of the Deferred returnValue('TWISTED IS GREAT!') else: # will trigger an errback raise Exception('DESTROY ALL LIFE')
阅读(2375) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~