单个回调 我们在上一节已经说过了
twisted中的延迟(deferred)(一)_zhangdell的专栏-CSDN博客
1:deffered 延迟链
from twisted.internet import defer
def myfun1(s):
print("myfun1 s=",s)
return "myfun1"
def myfun2(s):
print("myfun2 s=",s)
return "myfun2"
d = defer.Deferred()
d.addCallback(myfun1)
d.addCallback(myfun2)
d.callback("hello start")
myfun1 s= hello start
myfun2 s= myfun1
将多个回调加入延迟链中,第一个回调函数是用d.callback("hello start")触发的,而且要注意的是必须要有一个参数才能调用,因为callback是需要参数的,否则d.callback() 会报错(TypeError: callback() missing 1 required positional argument: 'result')。callback的参数是传给第一个回调函数的,所以第一个回调函数必须带一个参数。
第二个回调使用第一个回调的结果当做参数来执行计算,即使第一个回调函数没有返回值,第二个回调函数也必须带参数,这是这个形参的值是None罢了
myfun1 s= hello start
myfun2 s= None
也就是说myfunc1和myfunc2等设置的回调函数必须是要有一个参数的,即使myfun1没有任何返回值,myfunc2也必须是带参数的,否则 builtins.TypeError: myfun2() takes 0 positional arguments but 1 was given。
如果回调的过程中出现异常,将绕过回调链,切换到errback链。
def su_cb1(num):
num = num + 1
print("su_cb1=",num)
return num
def su_cb2(num):
num = num + 1
print("su_cb2=",num)
return num
def su_cb3(num):
num = num + 1
print("su_cb3=",num)
return num
def err_cb1(fail):
num = int(str(fail.value)) + 1
print("err_cb1",fail.type.__name__,fail.value,num)
if num < 10:
raise ValueError(num)
else:
return num
def err_cb2(fail):
num = int(str(fail.value)) + 1
print("err_cb2",fail.type.__name__,fail.value,num)
if num < 10:
raise ValueError(num)
else:
return num
def err_cb3(fail):
num = int(str(fail.value)) + 1
print("err_cb3",fail.type.__name__,fail.value,num)
if num < 10:
raise ValueError(num)
else:
return num
curnum = 8
d = defer.Deferred()
d.addCallback(su_cb1)
d.addCallback(su_cb2)
d.addErrback(err_cb1)
d.addErrback(err_cb2)
d.addCallback(su_cb3)
if curnum < 10:
d.errback(ValueError(curnum))
else:
d.callback(curnum)
调整curnum的值,以及callback errback的顺序 能模拟不同的情况。总之,正如上图那样,callback和errback 是可以相互切换的。如本例err_cb1--->err_cb2--->su_cb3,在回调err_cb2 num=10,正常返回,接着应该调用正常的callback,但是只回调err_cb2之后注册的callback连,也就是su_cb3,su_cb1和su_cb2由于是在err_cb2之前注册的,所以不在回调之列。
2:DeferredList
前边使用defer都是使用后不等待数据返回继续执行其他的操作,待数据就绪后再通过回调函数来处理数据。这些操作都是等待单一数据,但有时需要等待多份数据全部都返回后才能继续操作,这个时候就该DeferredList出场了。
deferrlist: 其所需等待的defer对象列表
fireOnOneCallback:
True:list列表中任一defer对象callback后,List就回调callback(只要有一个deferred调用了callback,list就会立即调用它的callback)
False:等待所有defer执行完。
fireOnOneErrback:deferrlist列表中任一defer对象errback后,如果deferr对象未指定errback,DeferredList就回调errback(只要有一个deferred调用了errback,list就会调用它的errback)
consumeErrors:deferrlist列表中任一defer对象执行过程中发生错误后,如果deferr对象未指定errback, DeferredList就回调errback
给consumeErrors
参数传递一个True
不会影响fireOnOneCallback
和fireOnOneErrback
的行为
from twisted.internet import defer
def myfun1(a):
print("myfun1--->",a)
return a
def myfun2(b):
print("myfun2--->",b)
return b
def myfun3(c):
print("myfun3--->",c)
return c
def err1(b):
print("err1--->",b)
return b
def err2(b):
print("err2--->",b)
return b
def err3(b):
print("err3--->",b)
return b
def printResult(result):
print("printResult--->",result)
def printErr(f):
print("printErr--->",f)
deferred1 = defer.Deferred()
deferred2 = defer.Deferred()
deferred3 = defer.Deferred()
deferred1.addCallback(myfun1)
deferred1.addErrback(err1)
deferred2.addCallback(myfun2)
deferred2.addErrback(err2)
deferred3.addCallback(myfun3)
deferred3.addErrback(err3)
dl = defer.DeferredList([deferred1, deferred2, deferred3], fireOnOneCallback=False,fireOnOneErrback=False,consumeErrors=False)
dl.addCallback(printResult)
dl.addErrback(printErr)
# deferred1.callback('one')
# deferred2.callback('two')
# deferred3.callback('three')
deferred1.errback(Exception('bang!'))
deferred2.errback(Exception('bang!'))
deferred3.errback(Exception('bang!'))
fireOnOneCallback=True,fireOnOneErrback=False,consumeErrors=True 和
fireOnOneCallback=False,fireOnOneErrback=False,consumeErrors=True 结果都是如下图
fireOnOneCallback=False,fireOnOneErrback=True,consumeErrors=True
先看 fireOnOneErrback,如果为True 当有错误时就执行list的errback,如果为False,不管fireOnOneCallback是True 还是False,最终都会执行list的callback。
consumeErrors 为False
consume为True
consume为True和False的结果,它不会影响fireOnOneCallback和fireOnOneErrback的结果。