Tornado的AsyncHTTPClient子类

2024-09-28 21:23:07 发布

您现在位置:Python中文网/ 问答频道 /正文

(python 3.6.4和tornado 4.5.3)

使用时: http客户端=tornado.httpclient.AsyncHTTPClient() 异步http请求获取工作正常。在

但是试图定义和使用AsyncHTTPClient的子类让我在运行程序时陷入了某种死锁(与同步HTTPClient类相反,它的一个子类运行良好)

*请纠正我:如果Tornado的AsynchHTTPClient类依附于/继承自可配置接口/抽象类,那么如何从中构建对象?(与Java中的规则相同?)。是不是有什么东西在几个内置的实现中选择了一个默认的实现?在

可配置子类必须定义可配置的基类和可配置的默认类方法,并使用实例方法initialize而不是init-在继承的情况下,默认的构造函数会调用super。init?这就是问题的原因吗?在

从文档中可以看出,不建议使用从AsyncHTTPClient继承/不是使用它的有效方法:

    http_client = AsyncHTTPClient()
    http_client.fetch("http://www.google.com/", handle_response)

这个类的构造函数在几个方面很神奇:它 实际创建特定于实现的实例 子类和实例作为一种伪单例重用 (每个.IOLoop一个)。关键字参数force_instance=True 可用于抑制此单例行为。除非 force_instance=True被使用,不应将任何参数传递给 AsyncHTTPClient构造函数。实现子类为 以及其构造函数的参数可以用 方法configure() 所有AsyncHTTPClient实现都支持defaults 关键字参数,可用于为设置默认值 HTTPRequest属性。例如:

^{pr2}$

其他问题:

1)缓冲响应是否是一种选择?在

3)我什么时候该上课tornado.web请求处理程序? 在


目前没有错误,但在实际获取之后我没有收到响应。在

import sys
from tornado import ioloop, gen, httpclient

在SimpleAsyncHTTPClient类下(httpclient.AsyncHTTPClient)公司名称:

#had to add this one (abstract function empty implementation? )
# I think that's the troublemaker
def fetch_impl(self, request, callback):
    pass

@gen.coroutine
def get(self, url):

    method = 'GET'
    print('send Async GET request ')
    res = yield self._fetch(url, method)
    print('after _fetch ...')
    return res

@gen.coroutine
def _fetch(self, url, method):
    print('send Asynchronous request ...')
    res = yield self.fetch(url, method=method)
    print('got a response')
    return res

在全球:

在@通用协同程序在

def ioloop_task():

yield gen.sleep(3)
url = 'http://google.com'
http_client = SimpleAsyncHTTPClient()

res = yield http_client.get(url)
res_code =  res.code
res_body =  res.body
print('return code: {}, body: {}....'.format(res_code, res_body[:60]))

print('do other stuff ....')
yield gen.sleep(2)

print(' task completed')

Tags: 方法selfclienthttpurldefresfetch
2条回答

但为什么呢?您可以使用AsyncHTTPClient。在

如果你这样做是为了学习,这里有一个概念的概要:

  1. yieldawait用于暂停协同程序。但它们不一样。然而,在Tornado中,当yield关键字在一个gen.coroutine修饰函数中时,它们都会执行相同的操作—即在将来(或awaitable)完成之前挂起一个协程。

  2. return用于从函数返回某些内容,我相信您已经知道了。


何时使用yield,何时使用await?在

如果使用的Python版本早于3.5,请使用@gen.coroutine ... yield语法。对于3.5+,应该使用async def ... await语法。另外,Tornado不久将推出drop support for older Python版本,因此最好遵守新语法。在

所以我要指出,把这两者混合起来似乎不是个好主意。通过将@gen.coroutine替换为async,并用await替换{},从而摆脱旧的语法。在


关于您的代码的一些注释:

让我们看看_fetchget方法。他们两个都不还钱。在

为了详细说明,在res = await self._fetch(url, method)get方法中,res将是{},因为{}没有返回任何内容。
同样的情况也发生在ioloop_taskres = http_client.get(url)res将是None,因为get没有返回任何内容。在

要解决这个问题,只需从_fetchget方法返回res对象。在

另外,您不需要_fetch方法。您可以在get方法中执行这些操作:

async def get(url):
    ...
    res = await self.fetch(url, method=method)
    return res

实际上,您甚至不需要async ... await语法。这同样有效:

^{pr2}$

为什么第二个代码示例可以很好地工作,我把它作为练习留给您去弄清楚。在

既然你用更多的细节更新了你的问题,而且它与原来的大不相同,我想再加一个答案。在

AsyncHTTPClient背后的魔力

考虑以下代码:

http_client = AsyncHTTPClient()
print(http_client.__class__)

# Output:
<class 'tornado.simple_httpclient.SimpleAsyncHTTPClient'>

如您所见,http_clientSimpleAsyncHTTPClient的实例,而不是{}。那么,这是怎么回事?在

如果您查看^{}的源代码,您将看到它继承了tornado.utils.Configurable类。在

Configurable类中最重要的一段代码是__new__方法,它负责所有的魔术。如果您查看它的source code,您会发现它将为类方法configurable_default返回的任何类创建一个实例。在

现在,看看^{}的源代码。它返回SimpleAsyncHTTPClient类,这就是为什么我们上面创建的对象(http_client)是SimpleAsyncHTTPClient的实例,而不是{}的实例。在

最后,是的,您是对的,您需要在子类中创建fetch_impl方法。因为AsyncHTTPClient将调用self.fetch_impl方法。您可以在this line in source code中看到这一点。在

虽然,fetch_impl没有在AsyncHTTPClient类中实现,但它已经在SimpleAsyncHTTPClient中实现。你可以找到它here。在


如何成功子类AsyncHTTPClient

{我需要先看看你的西装。在

相关问题 更多 >