- 浏览: 335367 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
ProgrammingPower:
非常感谢您,搞定了,哈哈!
Debian下安装CodeBlocks -
hfa1s2:
是的。谢谢你哈! 我解决了这个问题
python模块之smtplib: 用python发送SSL/TLS安全邮件 -
huangro:
587端口的是很麻烦的,毕竟是需要ssl验证的。
python模块之smtplib: 用python发送SSL/TLS安全邮件 -
hfa1s2:
我想利用内网往公司邮箱里发,但接口是587 的 而且需要 SS ...
python模块之smtplib: 用python发送SSL/TLS安全邮件 -
zyb88325:
你好 我现在用的cakephp2.0,因为服务器不支持rewr ...
CakePHP常用技巧总结
Twisted 采用异步处理并发事件,采用延时机制来实现这个功能,推荐看下面的原文,翻译太累,呵呵:
Trac back: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
Deferred Reference
This document is a guide to the behaviour of the twisted.internet.defer.Deferred
object, and to various
ways you can use them when they are returned by functions.
This document assumes that you are familiar with the basic principle that the Twisted framework is structured around: asynchronous, callback-based programming, where instead of having blocking code in your program or using threads to run blocking code, you have functions that return immediately and then begin a callback chain when data is available.
See these documents for more information:
After reading this document, the reader should expect to be able to deal with most simple APIs in Twisted and Twisted-using code that return Deferreds.
- what sorts of things you can do when you get a Deferred from a function call; and
- how you can write your code to robustly handle errors in Deferred code.
Unless you're already very familiar with asynchronous programming, it's strongly recommended you read the Deferreds section of the Asynchronous programming document to get an idea of why Deferreds exist.
Callbacks
A twisted.internet.defer.Deferred
is a promise that
a function will at some point have a result. We can attach callback functions
to a Deferred, and once it gets a result these callbacks will be called. In
addition Deferreds allow the developer to register a callback for an error,
with the default behavior of logging the error. The deferred mechanism
standardizes the application programmer's interface with all sorts of
blocking or delayed operations.
from twisted .internet import reactor , defer def getDummyData (x ): """ This function is a dummy which simulates a delayed result and returns a Deferred which will fire with that result. Don't try too hard to understand this. """ d = defer .Deferred () # simulate a delayed result by asking the reactor to fire the # Deferred in 2 seconds time with the result x * 3 reactor .callLater (2 , d .callback , x * 3 ) return d def printData (d ): """ Data handling function to be added as a callback: handles the data by printing the result """ print d d = getDummyData (3 ) d .addCallback (printData ) # manually set up the end of the process by asking the reactor to # stop itself in 4 seconds time reactor .callLater (4 , reactor .stop ) # start up the Twisted reactor (event loop handler) manually reactor .run ()
Multiple callbacks
Multiple callbacks can be added to a Deferred. The first callback in the Deferred's callback chain will be called with the result, the second with the result of the first callback, and so on. Why do we need this? Well, consider a Deferred returned by twisted.enterprise.adbapi - the result of a SQL query. A web widget might add a callback that converts this result into HTML, and pass the Deferred onwards, where the callback will be used by twisted to return the result to the HTTP client. The callback chain will be bypassed in case of errors or exceptions.
from twisted .internet import reactor , defer class Getter : def gotResults (self , x ): """ The Deferred mechanism provides a mechanism to signal error conditions. In this case, odd numbers are bad. This function demonstrates a more complex way of starting the callback chain by checking for expected results and choosing whether to fire the callback or errback chain """ if x % 2 == 0 : self .d .callback (x *3 ) else : self .d .errback (ValueError ("You used an odd number!" )) def _toHTML (self , r ): """ This function converts r to HTML. It is added to the callback chain by getDummyData in order to demonstrate how a callback passes its own result to the next callback """ return "Result: %s" % r def getDummyData (self , x ): """ The Deferred mechanism allows for chained callbacks. In this example, the output of gotResults is first passed through _toHTML on its way to printData. Again this function is a dummy, simulating a delayed result using callLater, rather than using a real asynchronous setup. """ self .d = defer .Deferred () # simulate a delayed result by asking the reactor to schedule # gotResults in 2 seconds time reactor .callLater (2 , self .gotResults , x ) self .d .addCallback (self ._toHTML ) return self .d def printData (d ): print d def printError (failure ): import sys sys .stderr .write (str (failure )) # this series of callbacks and errbacks will print an error message g = Getter () d = g .getDummyData (3 ) d .addCallback (printData ) d .addErrback (printError ) # this series of callbacks and errbacks will print "Result: 12" g = Getter () d = g .getDummyData (4 ) d .addCallback (printData ) d .addErrback (printError ) reactor .callLater (4 , reactor .stop ); reactor .run ()
Visual Explanation

- Requesting method (data sink) requests data, gets Deferred object.
- Requesting method attaches callbacks to Deferred object.

- When the result is ready, give it to the Deferred
object.
.callback(result)
if the operation succeeded,.errback(failure)
if it failed. Note thatfailure
is typically an instance of atwisted.python.failure.Failure
instance. - Deferred object triggers previously-added (call/err)back
with the
result
orfailure
. Execution then follows the following rules, going down the chain of callbacks to be processed.- Result of the callback is always passed as the first argument to the next callback, creating a chain of processors.
- If a callback raises an exception, switch to errback.
- An unhandled failure gets passed down the line of
errbacks, this creating an asynchronous analog to a
series to a series of
except:
statements. - If an errback doesn't raise an exception or return a
twisted.python.failure.Failure
instance, switch to callback.
Errbacks
Deferred's error handling is modeled after Python's exception handling. In the case that no errors occur, all the callbacks run, one after the other, as described above.
If the errback is called instead of the callback (e.g. because a DB query
raised an error), then a twisted.python.failure.Failure
is passed into the first
errback (you can add multiple errbacks, just like with callbacks). You can
think of your errbacks as being like except
blocks
of ordinary Python code.
Unless you explicitly raise
an error in except
block, the Exception
is caught and stops
propagating, and normal execution continues. The same thing happens with
errbacks: unless you explicitly return
a Failure
or (re-)raise an exception, the error stops
propagating, and normal callbacks continue executing from that point (using the
value returned from the errback). If the errback does returns a Failure
or raise an exception, then that is passed to the
next errback, and so on.
Note:
If an errback doesn't return anything, then it effectively
returns None
, meaning that callbacks will continue
to be executed after this errback. This may not be what you expect to happen,
so be careful. Make sure your errbacks return a Failure
(probably the one that was passed to it), or a
meaningful return value for the next callback.
Also, twisted.python.failure.Failure
instances have
a useful method called trap, allowing you to effectively do the equivalent
of:
try : # code that may throw an exception cookSpamAndEggs () except (SpamException , EggException ): # Handle SpamExceptions and EggExceptions ...
You do this by:
def errorHandler (failure ): failure .trap (SpamException , EggException ) # Handle SpamExceptions and EggExceptions d .addCallback (cookSpamAndEggs ) d .addErrback (errorHandler )
If none of arguments passed to failure.trap
match the error encapsulated in that Failure
, then
it re-raises the error.
There's another potential gotcha
here. There's a
method twisted.internet.defer.Deferred.addCallbacks
which is similar to, but not exactly the same as, addCallback
followed by addErrback
. In particular, consider these two cases:
# Case 1 d = getDeferredFromSomewhere () d .addCallback (callback1 ) # A d .addErrback (errback1 ) # B d .addCallback (callback2 ) d .addErrback (errback2 ) # Case 2 d = getDeferredFromSomewhere () d .addCallbacks (callback1 , errback1 ) # C d .addCallbacks (callback2 , errback2 )
If an error occurs in callback1
, then for Case 1
errback1
will be called with the failure. For Case
2, errback2
will be called. Be careful with your
callbacks and errbacks.
What this means in a practical sense is in Case 1, "A" will
handle a success condition from getDeferredFromSomewhere
, and
"B" will handle any errors that occur from either the upstream
source, or that occur in 'A'
. In Case 2, "C"'s errback1
will only handle an error condition raised by
getDeferredFromSomewhere
, it will not do any handling of
errors raised in callback1.
Unhandled Errors
If a Deferred is garbage-collected with an unhandled error (i.e. it would call the next errback if there was one), then Twisted will write the error's traceback to the log file. This means that you can typically get away with not adding errbacks and still get errors logged. Be careful though; if you keep a reference to the Deferred around, preventing it from being garbage-collected, then you may never see the error (and your callbacks will mysteriously seem to have never been called). If unsure, you should explicitly add an errback after your callbacks, even if all you do is:
# Make sure errors get logged from twisted .python import log d .addErrback (log .err )
Handling either synchronous or asynchronous results
In some applications, there are functions that might be either asynchronous or synchronous. For example, a user authentication function might be able to check in memory whether a user is authenticated, allowing the authentication function to return an immediate result, or it may need to wait on network data, in which case it should return a Deferred to be fired when that data arrives. However, a function that wants to check if a user is authenticated will then need to accept both immediate results and Deferreds.
In this example, the library function authenticateUser
uses the
application function isValidUser
to authenticate a user:
def authenticateUser (isValidUser , user ): if isValidUser (user ): print "User is authenticated" else : print "User is not authenticated"
However, it assumes that isValidUser
returns immediately,
whereas isValidUser
may actually authenticate the user
asynchronously and return a Deferred. It is possible to adapt this
trivial user authentication code to accept either a
synchronous isValidUser
or an
asynchronous isValidUser
, allowing the library to handle
either type of function. It is, however, also possible to adapt
synchronous functions to return Deferreds. This section describes both
alternatives: handling functions that might be synchronous or
asynchronous in the library function (authenticateUser
)
or in the application code.
Handling possible Deferreds in the library code
Here is an example of a synchronous user authentication function that might be
passed to authenticateUser
:
def synchronousIsValidUser (user ): ''' Return true if user is a valid user, false otherwise ''' return user in ["Alice" , "Angus" , "Agnes" ]
However, here's an asynchronousIsValidUser
function that returns
a Deferred:
from twisted .internet import reactor def asynchronousIsValidUser (d , user ): d = Deferred () reactor .callLater (2 , d .callback , user in ["Alice" , "Angus" , "Agnes" ]) return d
Our original implementation of authenticateUser
expected
isValidUser
to be synchronous, but now we need to change it to handle both
synchronous and asynchronous implementations of isValidUser
. For this, we
use maybeDeferred
to
call isValidUser
, ensuring that the result of isValidUser
is a Deferred,
even if isValidUser
is a synchronous function:
from twisted .internet import defer def printResult (result ): if result : print "User is authenticated" else : print "User is not authenticated" def authenticateUser (isValidUser , user ): d = defer .maybeDeferred (isValidUser , user ) d .addCallback (printResult )
Now isValidUser
could be either synchronousIsValidUser
or
asynchronousIsValidUser
.
It is also possible to modify synchronousIsValidUser
to return
a Deferred, see Generating Deferreds
for more
information.
DeferredList
Sometimes you want to be notified after several different events have all
happened, rather than waiting for each one individually. For example, you may
want to wait for all the connections in a list to close. twisted.internet.defer.DeferredList
is the way to do
this.
To create a DeferredList from multiple Deferreds, you simply pass a list of the Deferreds you want it to wait for:
# Creates a DeferredList dl = defer .DeferredList ([deferred1 , deferred2 , deferred3 ])
You can now treat the DeferredList like an ordinary Deferred; you can call
addCallbacks
and so on. The DeferredList will call its callback
when all the deferreds have completed. The callback will be called with a list
of the results of the Deferreds it contains, like so:
def printResult (result ): print result deferred1 = defer .Deferred () deferred2 = defer .Deferred () deferred3 = defer .Deferred () dl = defer .DeferredList ([deferred1 , deferred2 , deferred3 ]) dl .addCallback (printResult ) deferred1 .callback ('one' ) deferred2 .errback ('bang!' ) deferred3 .callback ('three' ) # At this point, dl will fire its callback, printing: # [(1, 'one'), (0, 'bang!'), (1, 'three')] # (note that defer.SUCCESS == 1, and defer.FAILURE == 0)
A standard DeferredList will never call errback.
If you want to apply callbacks to the individual Deferreds that go into the DeferredList, you should be careful about when those callbacks are added. The act of adding a Deferred to a DeferredList inserts a callback into that Deferred (when that callback is run, it checks to see if the DeferredList has been completed yet). The important thing to remember is that it is this callback which records the value that goes into the result list handed to the DeferredList's callback.
<!-- TODO: add picture here: three columns of callback chains, with a value being snarfed out of the middle of each and handed off to the DeferredList -->Therefore, if you add a callback to the Deferred after adding the Deferred to the DeferredList, the value returned by that callback will not be given to the DeferredList's callback. To avoid confusion, we recommend not adding callbacks to a Deferred once it has been used in a DeferredList.
def printResult (result ): print result def addTen (result ): return result + " ten" # Deferred gets callback before DeferredList is created deferred1 = defer .Deferred () deferred2 = defer .Deferred () deferred1 .addCallback (addTen ) dl = defer .DeferredList ([deferred1 , deferred2 ]) dl .addCallback (printResult ) deferred1 .callback ("one" ) # fires addTen, checks DeferredList, stores "one ten" deferred2 .callback ("two" ) # At this point, dl will fire its callback, printing: # [(1, 'one ten'), (1, 'two')] # Deferred gets callback after DeferredList is created deferred1 = defer .Deferred () deferred2 = defer .Deferred () dl = defer .DeferredList ([deferred1 , deferred2 ]) deferred1 .addCallback (addTen ) # will run *after* DeferredList gets its value dl .addCallback (printResult ) deferred1 .callback ("one" ) # checks DeferredList, stores "one", fires addTen deferred2 .callback ("two" ) # At this point, dl will fire its callback, printing: # [(1, 'one), (1, 'two')]
Other behaviours
DeferredList accepts three keyword arguments that modify its behaviour:
fireOnOneCallback
, fireOnOneErrback
and
consumeErrors
. If fireOnOneCallback
is set, the
DeferredList will immediately call its callback as soon as any of its Deferreds
call their callback. Similarly, fireOnOneErrback
will call errback
as soon as any of the Deferreds call their errback. Note that DeferredList is
still one-shot, like ordinary Deferreds, so after a callback or errback has been
called the DeferredList will do nothing further (it will just silently ignore
any other results from its Deferreds).
The fireOnOneErrback
option is particularly useful when you
want to wait for all the results if everything succeeds, but also want to know
immediately if something fails.
The consumeErrors
argument will stop the DeferredList from
propagating any errors along the callback chains of any Deferreds it contains
(usually creating a DeferredList has no effect on the results passed along the
callbacks and errbacks of their Deferreds). Stopping errors at the DeferredList
with this option will prevent Unhandled error in Deferred
warnings from
the Deferreds it contains without needing to add extra errbacks1
.
Class Overview
This is an overview API reference for Deferred from the point of using a Deferred returned by a function. It is not meant to be a substitute for the docstrings in the Deferred class, but can provide guidelines for its use.
There is a parallel overview of functions used by the Deferred's creator in Generating Deferreds .
Basic Callback Functions
-
addCallbacks(self, callback[, errback, callbackArgs, callbackKeywords, errbackArgs, errbackKeywords])
This is the method you will use to interact with Deferred. It adds a pair of callbacks parallel to each other (see diagram above) in the list of callbacks made when the Deferred is called back to. The signature of a method added using addCallbacks should be
myMethod(result, *methodArgs, **methodKeywords)
. If your method is passed in the callback slot, for example, all arguments in the tuplecallbackArgs
will be passed as*methodArgs
to your method.There are various convenience methods that are derivative of addCallbacks. I will not cover them in detail here, but it is important to know about them in order to create concise code.
-
addCallback(callback, *callbackArgs, **callbackKeywords)
Adds your callback at the next point in the processing chain, while adding an errback that will re-raise its first argument, not affecting further processing in the error case.
Note that, while addCallbacks (plural) requires the arguments to be passed in a tuple, addCallback (singular) takes all its remaining arguments as things to be passed to the callback function. The reason is obvious: addCallbacks (plural) cannot tell whether the arguments are meant for the callback or the errback, so they must be specifically marked by putting them into a tuple. addCallback (singular) knows that everything is destined to go to the callback, so it can use Python's * and ** syntax to collect the remaining arguments.
-
addErrback(errback, *errbackArgs, **errbackKeywords)
Adds your errback at the next point in the processing chain, while adding a callback that will return its first argument, not affecting further processing in the success case.
-
addBoth(callbackOrErrback, *callbackOrErrbackArgs, **callbackOrErrbackKeywords)
This method adds the same callback into both sides of the processing chain at both points. Keep in mind that the type of the first argument is indeterminate if you use this method! Use it for
finally:
style blocks.
-
Chaining Deferreds
If you need one Deferred to wait on another, all you need to do is return a Deferred from a method added to addCallbacks. Specifically, if you return Deferred B from a method added to Deferred A using A.addCallbacks, Deferred A's processing chain will stop until Deferred B's .callback() method is called; at that point, the next callback in A will be passed the result of the last callback in Deferred B's processing chain at the time.
If this seems confusing, don't worry about it right now -- when you run into a situation where you need this behavior, you will probably recognize it immediately and realize why this happens. If you want to chain deferreds manually, there is also a convenience method to help you.
-
chainDeferred(otherDeferred)
Add
otherDeferred
to the end of this Deferred's processing chain. When self.callback is called, the result of my processing chain up to this point will be passed tootherDeferred.callback
. Further additions to my callback chain do not affectotherDeferred
This is the same as
self.addCallbacks(otherDeferred.callback, otherDeferred.errback)
See also
- Generating Deferreds , an introduction to writing asynchronous functions that return Deferreds.
Footnotes
Version: 8.1.0
发表评论
-
Trac Data Models and Schema
2010-09-15 10:56 6375The main models that developers ... -
在Mac OS上运行wxPython
2010-09-14 15:42 3231如果在一个64位的Mac上跑wxPython, 将会出现以下错 ... -
Trac SQL Database API
2010-09-14 13:41 1054Trac SQL Database API Trac use ... -
Trac系统相关文档
2010-02-01 12:53 10691. Trac组件架构 http://trac.edgewal ... -
Django上传文件
2009-11-26 18:06 1368之前写了一个上传文件模块,但是当文件很大时就会挂掉,分析了一下 ... -
50个Python重要模块
2009-10-20 09:32 1998原文地址:http://www.cnblogs.com/yd1 ... -
Trac系统的双重认证
2009-10-20 09:27 1154首先,需要导入urllib2及cookielib。 然后,关键 ... -
分享一个图表制作库
2009-06-18 15:15 1324该包名为ChartDirector,可以从其官方主页http: ... -
django newforms的更改
2009-06-16 13:34 1067Django升级之后,有一些应用包的名称也相应发生了变化,比如 ... -
Python版支付宝集成插件源代码
2009-05-08 15:34 4930之前在做一项目的时候需要集成支付宝功能,网站是用python做 ... -
Django多语言问题
2009-05-06 17:22 1919最近多Django比较感兴趣,打算用它来做一个网站,看了官方关 ... -
Installing Satchmo on Webfaction
2009-04-29 15:39 1665link: http://brianmckinney.net/ ... -
Satchmo配置注意事项
2009-04-25 16:10 1040Satchmo在同步数据库之后,在操作后台管理页面过程中,一直 ... -
Yaml与python类型的对照表
2009-04-22 23:03 1710因为常用yaml作为python程序的配置文件,特将其与pyt ... -
satchmo汉化
2009-04-21 15:21 1919转载:http://blog.csdn.net/huliuhe ... -
python模块之smtplib: 用python发送SSL/TLS安全邮件
2008-07-04 19:08 9474原文出自 http://blog.csdn.net/zhaow ... -
python模块之poplib: 用pop3收取邮件
2008-07-04 19:09 2216python的poplib模块是用来 ... -
python模块之email: 电子邮件编码解码 (转)
2008-07-04 19:11 3522用email模块来生成邮件也是很简单的,只是需要一些mime的 ... -
用iconv做通用的语言编码转换(转)
2008-07-04 19:13 1387#include <stdio.h> #in ... -
python模块之email: 电子邮件编码解码(转)
2008-07-04 19:16 3297出处:http://blog.csdn.net/zhaowei ...
相关推荐
8. **安全性**:Twisted包含了一些安全相关的组件,如加密套接字和认证机制,使得开发安全的网络应用变得更加容易。 9. **国际化和本地化**:Twisted支持多种语言,可以方便地实现应用的国际化和本地化。 10. **...
3. **中间件**:Scrapy的中间件机制允许自定义下载和解析逻辑,这些逻辑通常需要处理网络通信,而Twisted则提供了底层的支持。 4. **爬虫**:爬虫组件通过Twisted异步处理HTTP请求,获取网页内容,然后使用XPath或...
- **捕获它,Twisted**:这部分详细说明了如何使用Twisted的错误处理机制来捕获和处理异常。 #### 第四部分:由Twisted支持的诗歌客户端 - **Twisted接口**:介绍了Twisted提供的API接口,以及如何使用这些接口来...
Twisted是一个基于Python的异步网络编程库,提供了一个灵活的架构来处理异步I/O操作。该教程将从基础开始,逐步深入Twisted的世界,帮助读者了解异步编程的思想和Twisted的使用方法。 异步编程模型 异步编程模型是...
在实际使用Twisted时,往往需要从底层机制开始,逐步理解其抽象层次。Twisted提供了高度抽象的接口,使得异步编程更为简洁,但这也增加了初学者的学习难度。 异步编程的优势在于,它可以在单线程环境中实现任务的...
5. **延迟调用与定时器**:Twisted提供了延迟调用(Deferred)机制,用于处理异步操作的结果。示例可能演示如何使用延迟调用来处理未来的操作。 6. **认证与加密**:Twisted包含了多种安全协议,如SSL/TLS加密,...
这种设计使得Twisted能够同时处理多个连接,极大地提高了性能和效率。 ### 2. I/O服务 Twisted提供了多种I/O服务,包括TCP、UDP、SSL/TLS、UNIX域套接字等。开发者可以通过简单的接口创建服务器和客户端,例如: ...
而reactor模式则是Twisted框架中用来响应事件的机制。 接下来,在第二部分中,教程带领读者初探异步编程,并且介绍了reactor模式的具体使用。这里通过实现一个简单的诗歌服务器来演示reactor模式的运作方式,分别在...
在Scrapy中,Twisted用于处理网络请求和响应,实现高效的并发和非阻塞I/O操作。安装Scrapy时,如果系统中的Twisted版本过旧或者与Scrapy不兼容,可能会导致安装失败。 1. 安装Scrapy的步骤: - 首先,确保已经安装...
通过对Reactor模型和Deferred机制的学习,开发者可以更好地理解和掌握Twisted的核心思想,进而有效地利用Twisted解决实际问题。无论是对于初学者还是经验丰富的开发者来说,Twisted都提供了丰富的工具和API,帮助...
8. **并发与并发控制**:Twisted的并发机制包括了线程池和工作队列,可以用于执行耗时的计算任务,而不会阻塞网络I/O。 9. **测试工具**:Twisted还包含了一套强大的测试框架,如`trial`,它支持异步测试,可以对...
7. **Concurrency**: 除了传统的回调机制,`Twisted` 还引入了协程(`Deferred`)的概念,使得异步编程更加直观和易于管理。 8. **Testing**: `Twisted` 内置了测试框架` Trial`,用于编写和执行单元测试,确保代码的...
Twisted 是一个开源的 Python 网络编程框架,专为异步网络编程设计,广泛应用于网络服务、客户端、协议实现和并发处理。其核心设计围绕事件驱动模型,使得开发者可以编写高性能、高并发的网络应用。本教程将深入探讨...
相比之下,Twisted 采用了异步和事件驱动的设计模式,这意味着它能够在处理网络事件的同时保持程序的响应性,而无需依赖多线程。 ##### 1.3 多功能性 Twisted 提供了广泛的功能集合,几乎涵盖了所有常见的网络应用...
4. **异步非阻塞IO**:Twisted 基于异步非阻塞IO模型,可以显著提高系统的响应速度和处理能力,特别适合高并发的网络应用。 #### 二、Twisted的关键概念 1. **事件循环(Event Loop)**:Twisted的核心是一个事件...
在Twisted框架中,Reactor模式是实现异步编程的核心组件,它是对观察者模式的实现,能够响应并处理不同类型的事件。Twisted框架使用事件循环来监控事件源,当事件发生时触发回调函数。 本教程深入介绍了Twisted的...
它的核心在于异步I/O模型,通过回调机制处理网络事件,使得程序可以高效地处理大量并发连接。 2. **文件传输系统架构** 在这个系统中,分为两个主要部分:服务器端和客户端。服务器端负责接收文件请求并发送文件...