Derferreds这个东西很好用
举个常规的例子,进行写文件的操作
1 file=open('file.txt')2 file.write('ok')3 file.close()
在Twisted中可以这样
1 file=open('file.txt')2 file.addCallback(write)3 file.addCallbacl(close)
1 open('file.txt').addCallback(write).addCallbacl(close)
如果想加入异常处理,不需要try,except捕捉
d = open()d.addErrback(report_error)
或者最简单粗暴地
1 d.addCallbacks(h, g)
其中h是方法,g是异常。
传统地编写Twisted代码风格如下:
1 def getUsers():2 d = makeRequest("GET", "/users")3 d.addCallback(json.loads)4 return d
d的返回值会作为参数传给下一个回调函数
但是Twisted内置了一个方法,可以让我们在不编写回调函数的情况下使用Deferreds,使用一个装饰器,代价仅仅是把原先的传统写法改为生成器
我们不需要调用addCallback,makeRequest会直接返回结果
总而言之,记住不是用return返回,而是returnValue
但是在python3以上,可以直接使用return json.loads(responseBody),但是会导致不兼容python2
1 from twisted.internet.defer import inlineCallbacks, returnValue2 3 @inlineCallbacks4 def getUsers(self):5 responseBody = yield makeRequest("GET", "/users")6 returnValue(json.loads(responseBody))
如果想在上边添加异常处理的话,可以用简单粗暴的方式addCallbacks
1 def getUsers(): 2 d = makeRequest("GET", "/users") 3 4 def connectionError(failure): 5 failure.trap(ConnectionError) 6 log.failure("makeRequest failed due to connection error", 7 failure) 8 return [] 9 10 d.addCallbacks(json.loads, connectionError)11 return d
如果是用上边的装饰器捷径的话,可以考虑下边的写法,由于我们不调用addCallback,所以只能进行try捕捉了
1 @inlineCallbacks2 def getUsers(self):3 try:4 responseBody = yield makeRequest("GET", "/users")5 except ConnectionError:6 log.failure("makeRequest failed due to connection error")7 returnValue([])8 9 returnValue(json.loads(responseBody))
可以用协程来实现
1 import json 2 from twisted.internet.defer import ensureDeferred 3 from twisted.logger import Logger 4 log = Logger() 5 6 async def getUsers(): 7 try: 8 return json.loads(await makeRequest("GET", "/users")) 9 except ConnectionError:10 log.failure("makeRequest failed due to connection error")11 return []12 13 def do():14 d = ensureDeferred(getUsers())15 d.addCallback(print)16 return d
可以直接在上边加wait
1 async def foo(): 2 res = await someFunctionThatReturnsADeferred() 3 return res 4 5 async def bar(): 6 baz = await someOtherDeferredFunction() 7 fooResult = await foo() 8 return baz + fooResult 9 10 def myDeferredReturningFunction():11 coro = bar()12 return ensureDeferred(coro)