twisted:`defer.execute`和`threads.deferToThread`之间的区别

Cla*_*diu 8 python multithreading twisted deferred-execution

是什么区别defer.execute(),并threads.deferToThread()在扭曲?两者都使用相同的参数 - 一个函数,以及用它调用它的参数 - 并返回一个deferred,它将通过调用函数的结果触发.

threads版本明确声明它将在一个线程中运行.但是,如果defer版本没有,那么调用它有什么意义呢?在reactor中运行的代码永远不会阻塞,因此它调用的任何函数都不能阻塞.那时,您可以做defer.succeed(f(*args, **kwargs))而不是defer.execute(f, args, kwargs)使用相同的结果.

Cra*_*ast 9

defer.execute确实在阻塞的方式执行功能,在同一个线程,你是正确的在defer.execute(f, args, kwargs)做相同的defer.succeed(f(*args, **kwargs)) ,除了defer.execute将返回已如果函数打响了errback可回调˚F抛出异常.同时,在你的defer.succeed示例中,如果函数抛出异常,它将向外传播,这可能是不希望的.

为了便于理解,我只需在此处粘贴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)
Run Code Online (Sandbox Code Playgroud)

换句话说,defer.execute仅仅是一个快捷方式取一个阻塞函数的结果作为递延然后您可以添加回调/ errbacks来.回调将使用正常的链接语义触发.这看起来有点疯狂,但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
Run Code Online (Sandbox Code Playgroud)

要在没有reactor的同步上下文中运行它,你可以只传递一个替代的getter函数,如下所示:

from urllib2 import urlopen

def synchronous_getter(url):
    resp = urlopen(url)
    result = resp.read()
    resp.close()
    return result
Run Code Online (Sandbox Code Playgroud)