Python 使用扭曲的';是以URL打开的方式获取页面吗?

Python 使用扭曲的';是以URL打开的方式获取页面吗?,python,django,twisted,urllib2,urllib,Python,Django,Twisted,Urllib2,Urllib,我想在webapp中使用Twisted非阻塞getPage方法,但与urlopen相比,使用这样的函数感觉相当复杂 这是我试图实现的一个例子: def web_request(request): response = urllib.urlopen('http://www.example.org') return HttpResponse(len(response.read())) 与getPage有类似的东西有那么难吗?关于非阻塞操作(您似乎明确希望)要了解的是,您不能真正用它们

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

这是我试图实现的一个例子:

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


与getPage有类似的东西有那么难吗?

关于非阻塞操作(您似乎明确希望)要了解的是,您不能真正用它们编写顺序代码。操作不会阻塞,因为它们不会等待结果。它们启动操作并将控制权返回到您的函数。因此,
getPage
不会返回像您可以从中读取的对象那样的文件。即使它这样做了,在数据可用之前(或者它会阻塞)您也无法从中读取数据,因此您不能对其调用
len()
,因为这需要先读取所有数据(这会阻塞)

Twisted中处理非阻塞操作的方法是通过
延迟
,延迟是用于管理回调的对象
getPage
返回一个
Deferred
,这意味着“您稍后将获得此结果”。在获得结果之前,您无法对结果执行任何操作,因此您将回调添加到
延迟的
,当结果可用时,
延迟的
将调用这些回调。然后,该回调可以执行您希望它执行的操作:

def web_request(request)
    def callback(data):
        HttpResponse(len(data))
    d = getPage("http://www.example.org")
    d.addCallback(callback)
    return d
示例中的另一个问题是,
web\u请求
函数本身被阻塞。在等待
getPage
的结果可用时,您想做什么?在
web\u请求中执行其他操作
,还是等待?或者您想将
web\u请求
本身变为非阻塞?如果是,您希望如何产生结果?(Twisted中的明显选择是返回另一个
延迟的
——或者甚至是与
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))
与显式返回
d
Deferred的示例类似,这仅在调用方希望
web\u请求
是非阻塞的情况下才起作用--
defer.inlineCallbacks
装饰器将生成器转换为一个函数,该函数将
延迟的
I返回到最近使用
getPage
从URL获取内容所需的最小代码量。以下是完整性:

from twisted.web.client import getPage
from twisted.internet import reactor

url = 'http://aol.com'

def print_and_stop(output):
    print output
    if reactor.running:
       reactor.stop()

if __name__ == '__main__':
    print 'fetching', url
    d = getPage(url)
    d.addCallback(print_and_stop)
    reactor.run()

请记住,您可能需要更深入地了解Twisted处理事件时使用的(
getPage
在本例中,触发是一个事件)。

@Thomas:感谢您的精彩回复!!:D不幸的是,第一个示例返回的是延迟对象,而不是HttpResponse对象!!您的代码也没有返回HttpResponse对象,但是是的,这可以归结为我所解释的调用方希望
web\u请求被阻塞。如果不改变它的调用方式,你就不能将某个东西从阻塞改为非阻塞。我是说这一点很不简单。@Thomas:如果我使用一个带超时的while循环怎么办|RadiantHex,您必须接受,如果您想要非阻塞操作,就不能使用阻塞代码。