twisted官方文档
https://twistedmatrix.com/documents/current/index.html
deferred 详细说明
Deferred Reference — Twisted 21.2.0 documentation
关于deferred的通俗理解
1:deferred说“我是一个信号,只是通知你不管你刚才要我做的什么,结果还没有出来”
2:你可以让Deferred在结果出来后执行你的回调函数
Deferred关键之处:
1:Deferreds将会在调用其callback或errback时被触发;
2:Deferreds仅能被触发一次(通过Deferred对象的callback or errback触发)如果尝试多次触发将会导致AlreadyCalledError异常;
3:第N级callback或errback中的Exceptions将会传入第N+1级的errback中;如果没有errback,则会抛出Unhandled Error。如果第N级callback或errback中没有抛出Exception或返回Failure对象,那接下来将会由第N+1级中的callback进行处理;
4:callback中返回的结果将会传入下一级callback,并作为其第一个参数;
5:如果传入errback的错误不是一个Failure对象,那将会被自动包装一次。
具体实例
1:初识deferred,简单使用
from twisted.internet import defer
def result(num):
print("result:",num)
print("start")
num = 100
d = defer.Deferred()
d.addCallback(result)
d.callback(num + 1)
print("end")
输出结果:
start
result: 101
end
由于上边的test 只是简单的执行num + 1操作,不存在任何耗时的操作,所以看不出啥效果。
2:deferred联合定时器 延时调用
from twisted.internet import reactor
from twisted.internet import defer
import time
def result(num):
print("result:",num,time.time())
print("start",time.time())
num = 100
d = defer.Deferred()
reactor.callLater(5,d.callback,num + 1)
d.addCallback(result)
print("end",time.time())
reactor.run()
输出结果:
start 1646104831.686
end 1646104831.686
result: 101 1646104836.686
延时5s后调用defer的callback回调函数并且传入一个数值(num + 1),101在结果当中已经正确显示
3:deferred设置成功和错误回调
from twisted.internet import defer
def result(num):
print("result:",num)
def err_result(failure):
print("err_result:",failure)
print("start")
num = 100
d = defer.Deferred()
d.addCallback(result)
d.addErrback(err_result)
#d.addCallbacks(result,err_result)
d.callback(num + 1)
# d.errback(ValueError("hello error"))
print("end")
start
result: 101
end
start
err_result: [Failure instance: Traceback (failure with no frames): <class 'ValueError'>: hello error
]
end
d.addCallbacks(result,err_result) 是 d.addCallback(result)和d.addErrback(err_result) 这2行代码合并,而且d.callback(num + 1)和 d.errback(ValueError("hello error")) 只能选择执行一行,否则会导致AlreadyCalledError错误。从errback执行的结果可以看出Twisted会把错误封装在Failure里。
from twisted.internet import reactor,defer
def func_success(result):
print(result)
def func_error(fail):
print(fail)
print("func_error <%s>-<%s>" % (fail.type.__name__,fail.value))
print(fail.getBriefTraceback())
num = "1"
d = defer.Deferred()
if isinstance(num,int):
reactor.callLater(2,d.callback,num + 1)
else:
reactor.callLater(2,d.errback,ValueError('error type'))
d.addCallback(func_success).addErrback(func_error)
reactor.run()
除了addCallback addErrback addCallbacks 还有一个addBoth、addTimeout