python – 使用Twisted的getPage作为urlopen?

我想在webapp中使用Twisted非阻塞getPage方法,但与urlopen相比,使用这样的函数感觉相当复杂.

这是我想要实现的一个例子:

def web_request(request):
   response = urllib.urlopen('http://www.example.org')
   return HttpResponse(len(response.read()))

与getPage有类似的东西是如此困难吗?

最佳答案
关于非阻塞操作(你似乎明确想要的)实现的是你无法用它们真正编写顺序代码.操作不会阻止,因为它们不会等待结果.他们启动操作并将控制权返回给您的功能.因此,getPage不会返回像urllib.urlopen那样可以读取的类文件对象.即使它确实如此,在数据可用之前你也无法从中读取(或者它会阻塞.)所以你不能在它上面调用len(),因为它需要首先读取所有数据(这会块.)

在Twisted中处理非阻塞操作的方法是通过Deferreds,它是用于管理回调的对象. getPage返回Deferred,表示“稍后会得到此结果”.在获得结果之前,您无法对结果执行任何操作,因此您将回调添加到Deferred,并且Deferred将在结果可用时调用这些回调.那个回调可以做你想要的:

def web_request(request)
    def callback(data):
        HttpResponse(len(data))
    d = getPage("http://www.example.org")
    d.addCallback(callback)
    return d

您的示例的另一个问题是您的web_request函数本身是阻塞的.等待getPage的结果可用时你想做什么?在web_request中做其他事情,或者只是等待?或者您想将web_request本身变为非阻塞?如果是这样,您希望如何产生结果? (Twisted中显而易见的选择是返回另一个Deferred – 或者甚至与getPage返回的相同,如上例所示.但是,如果你在另一个框架中编写代码,这可能并不总是合适的.)

有一种方法可以使用Deferreds编写顺序代码,虽然它有点限制,更难调试,并且核心Twisted人在你使用它时会哭:twisted.internet.defer.inlineCallbacks.它使用Python 2.5中的新生成器功能,您可以将数据发送到生成器,代码看起来像这样:

@defer.inlineCallbacks
def web_request(request)
    data = yield getPage("http://www.example.org")
    HttpResponse(len(data))

就像显式返回d Deferred的示例一样,只有当调用者期望web_request是非阻塞的时,这才会起作用–defer.inlineCallbacks装饰器将生成器转换为返回Deferred的函数.

转载注明原文:python – 使用Twisted的getPage作为urlopen? - 代码日志