Python twisted:'defer.execute'和'threads.deferToThread'之间的区别`
twisted中的Python twisted:'defer.execute'和'threads.deferToThread'之间的区别`,python,multithreading,twisted,deferred-execution,Python,Multithreading,Twisted,Deferred Execution,twisted中的defer.execute()和threads.deferToThread()之间有什么区别?两者都采用相同的参数—一个函数和调用它的参数—并返回一个延迟参数,该参数将与调用函数的结果一起触发 threads版本明确声明它将在线程中运行。但是,如果延迟版本没有,那么调用它有什么意义呢?在反应器中运行的代码不应该阻塞,因此它调用的任何函数都不应该阻塞。此时,您可以只执行defer.success(f(*args,**kwargs))而不执行defer.execute(f,args
defer.execute()
和threads.deferToThread()
之间有什么区别?两者都采用相同的参数—一个函数和调用它的参数—并返回一个延迟参数,该参数将与调用函数的结果一起触发
threads
版本明确声明它将在线程中运行。但是,如果<代码>延迟代码>版本没有,那么调用它有什么意义呢?在反应器中运行的代码不应该阻塞,因此它调用的任何函数都不应该阻塞。此时,您可以只执行defer.success(f(*args,**kwargs))
而不执行defer.execute(f,args,kwargs)
,并获得相同的结果。defer.execute确实以阻塞方式在同一线程中执行函数,并且您的defer.execute(f,args,kwargs)是正确的
的操作与defer.success(f(*args,**kwargs))
相同,只是defer.execute将返回一个回调,如果函数f引发异常,则该回调已触发errback。同时,在您的defer.success示例中,如果函数抛出异常,它将向外传播,这可能是不需要的
为了便于理解,我将在此处粘贴defer.execute的源代码:
def execute(callable, *args, **kw):
"""Create a deferred from a callable and arguments.
Call the given function with the given arguments. Return a deferred which
has been fired with its callback as the result of that invocation or its
errback with a Failure for the exception thrown.
"""
try:
result = callable(*args, **kw)
except:
return fail()
else:
return succeed(result)
换句话说,defer.execute
只是一个快捷方式,可以将阻塞函数的结果作为延迟结果,然后可以将回调/错误回调添加到延迟结果中。回调将使用正常的链接语义触发。这似乎有点疯狂,但延迟可以在添加回调之前“触发”,回调仍然会被调用
那么,为了回答你的问题,为什么这个有用呢?那么,defer.execute
对于测试/模拟以及简单地将异步api与同步代码集成都很有用
同样有用的还有defer.maybeDeferred
,它调用函数,如果函数已经返回了一个deferred,那么只返回它,其他函数类似于defer.execute
。当您编写一个API时,这很有用,该API需要一个可调用的函数,当调用该函数时,它会给您一个延迟的函数,并且您希望能够接受正常的阻塞函数
例如,假设您有一个应用程序,它获取页面并使用它进行操作。而且,出于某种原因,您需要为特定用例以同步方式运行它,比如在单次crontab脚本中,或者响应WSGI应用程序中的请求,但仍然保持相同的代码库。如果您的代码如下所示,则可以执行以下操作:
from twisted.internet import defer
from twisted.web.client import getPage
def process_feed(url, getter=getPage):
d = defer.maybeDeferred(getter, url)
d.addCallback(_process_feed)
def _process_feed(result):
pass # do something with result here
要在同步上下文中运行它,而不使用reactor,只需传递一个备用getter函数,如下所示:
from urllib2 import urlopen
def synchronous_getter(url):
resp = urlopen(url)
result = resp.read()
resp.close()
return result