Twisted中的defer.execute()
和threads.deferToThread()
有什么区别?两者都使用相同的参数-一个函数,以及使用该函数调用的参数-并返回一个deferred,该延迟将与调用该函数的结果一起触发。threads
版本明确声明它将在线程中运行。但是,如果没有defer
版本,那么调用它会是什么意义呢?在 react 堆中运行的代码绝不应该阻塞,因此它调用的任何函数都必须不阻塞。那时,您可以只执行defer.succeed(f(*args, **kwargs))
而不是defer.execute(f, args, kwargs)
即可获得相同的结果。
最佳答案
defer.execute确实确实以阻塞方式在同一线程中执行了该函数,并且您的正确之处在于defer.execute(f, args, kwargs)
与defer.succeed(f(*args, **kwargs))
相同,但除外,defer.execute
将返回回调,如果函数 f 抛出该错误,则该回调已引发错误一个异常(exception)。同时,在延迟成功的示例中,如果函数引发异常,则它将向外传播,这可能是不希望的。
为了便于理解,我将在此处粘贴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
只是将阻止函数的结果作为延迟的快捷方式,然后可以向其添加回调/错误返回。回调将使用常规的链接语义触发。似乎有些疯狂,但是Deferreds可以在添加回调之前“触发”,并且仍将调用这些回调。因此,回答您的问题,这为什么有用?好吧,
defer.execute
对于测试/模拟以及简单地将异步api与同步代码集成在一起都是很有用的。defer.maybeDeferred
也很有用,它会调用该函数,然后如果该函数已经返回了deferred,则只需返回它,否则调用类似于defer.execute
的函数。当您编写一个期望可调用的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
要在没有反应堆的情况下在同步上下文中运行此代码,您可以仅传递一个替代的getter函数,如下所示:
from urllib2 import urlopen
def synchronous_getter(url):
resp = urlopen(url)
result = resp.read()
resp.close()
return result
关于python - 扭曲: `defer.execute`和 `threads.deferToThread`之间的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3686608/