龙卷风的AsyncHTTPClient子类

时间:2018-01-11 15:56:25

标签: python python-3.x oop asynchronous tornado

(python 3.6.4和龙卷风4.5.3)

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

但是,在运行程序时,尝试定义和使用AsyncHTTPClient的子类会让我陷入某种死锁状态(而不是同步的HTTPClient类,其中的子类运行良好)

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

"可配置的子类必须定义类方法configurable_base和configurable_default,并使用实例方法初始化而不是 init 。 " - 继承的默认ctor是否会调用super。 init ?这是问题的原因吗?

从文档看来,不推荐继承AsyncHTTPClient /不是使用它的有效方法:

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

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

AsyncHTTPClient.configure(
    None, defaults=dict(user_agent="MyUserAgent"))
# or with force_instance:
client = AsyncHTTPClient(force_instance=True,
    defaults=dict(user_agent="MyUserAgent"))

其他问题:

1)缓冲响应是否是一个选择问题?

3)我什么时候应该使用tornado.web.RequestHandler?

这个类

目前没有错误但我在实际获取后没有收到回复。

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

在全球范围内:

@ gen.coroutine

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')

2 个答案:

答案 0 :(得分:0)

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

如果你这样做是为了学习,这里是概念的概述:

  1. yieldawait用于暂停协程。但他们不一样。但是,在Tornado中,当yield关键字位于gen.coroutine修饰函数中时,它们都执行相同的操作 - 即挂起协程直到将来(或awaitable)完成。

  2. return用于从函数返回一些东西,我相信你已经知道了。

  3. 何时使用yield以及何时使用await

    如果您使用的是早于3.5的Python,请使用@gen.coroutine ... yield语法。对于3.5+,您应该使用async def ... await语法。此外,Tornado即将发布drop support for older Python版本,因此最好遵守新语法。

    这让我指出混合这两者似乎并不是一个好主意。通过将@gen.coroutine替换为async并将yield替换为await来摆脱旧语法。

    关于您的代码的一些评论:

    我们来看看_fetchget方法。他们俩都没有回来。

    详细说明一下,get方法res = await self._fetch(url, method) res None_fetch ioloop_task,因为res = http_client.get(url)没有返回任何内容。
    res None get也发生了同样的情况。 res_fetch,因为get没有返回任何内容。

    要解决此问题,只需从_fetchget方法返回async def get(url): ... res = await self.fetch(url, method=method) return res 对象即可。

    此外,您并不真正需要async ... await方法。您可以使用def get(url): ... return self.fetch(url, method=method) 方法执行这些操作:

       Observation month A/C num
    
    2010-09                 abc1
    2010-10                 abc1
    2010-11                  xyz
    

    实际上,您甚至不需要{{1}}语法。这样可以正常工作:

    {{1}}

    为什么第二个代码示例可以正常工作,我将其留作练习让你弄明白。

答案 1 :(得分:0)

由于您已经使用其他详细信息更新了问题,并且它与原始版本有很大不同,我会添加另一个答案。

AsyncHTTPClient背后的魔力

考虑以下代码:

http_client = AsyncHTTPClient()
print(http_client.__class__)

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

如您所见,http_clientSimpleAsyncHTTPClient的实例,而不是AsyncHTTPClient。那么,这里发生了什么?

如果查看https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher的源代码,您会看到它继承了tornado.utils.Configurable类。

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

现在,查看source code的源代码。它返回SimpleAsyncHTTPClient类,这就是我们在上面创建的对象(http_client)是SimpleAsyncHTTPClient的实例,而不是AsyncHTTPClient的实例。

最后,是的,您需要在子类中创建fetch_impl方法。因为AsyncHTTPClient会调用self.fetch_impl方法。您可以在AsyncHTTPClient.configurable_default中看到此信息。

虽然fetch_impl类中尚未实现AsyncHTTPClient,但它已在SimpleAsyncHTTPClient中实施。你可以找到它this line in source code

如何成功继承AsyncHTTPClient

我首先查看here并根据您的需要进行修改。