使用Twisted的getPage作为urlopen?

Rad*_*Hex 5 python django twisted urllib urllib2

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

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

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

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

Tho*_*ers 20

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

在Twisted中处理非阻塞操作的方法是通过Deferreds,它是用于管理回调的对象.getPage返回a Deferred,表示"稍后会得到此结果".你不能用结果做什么,直到你得到它,所以你添加回调Deferred,而Deferred将调用这些回调的时候,结果可用的.那个回调可以做你想要的:

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

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

还有就是编写使用顺序代码的方式Deferreds,虽然它有点限制,难以调试,当你使用它的核心扭曲人们的哭泣:twisted.internet.defer.inlineCallbacks.它使用Python 2.5中的新生成器功能,您可以将数据发送到生成器,代码看起来像这样:

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

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

  • RadiantHex,你将不得不接受如果你想要非阻塞操作,你就不能使用阻塞代码. (2认同)