【问题标题】:Future exception was never retrieved未来的异常从未被检索到
【发布时间】:2017-04-29 18:32:35
【问题描述】:

我有一个抓取工具(基于 Python 3.4.2 和 asyncio/aiohttp 库)和一堆链接(> 10K)来检索少量数据。 部分爬虫代码:

@asyncio.coroutine
def prepare(self, links):
    semaphore = asyncio.Semaphore(self.limit_concurrent)
    tasks = []
    result = []

    tasks = [self.request_data(link, semaphore) for link in links]

    for task in asyncio.as_completed(tasks):
        response = yield from task
        if response:
            result.append(response)
        task.close()
    return result

@asyncio.coroutine
def request_data(self, link, semaphore):

    ...

    with (yield from semaphore):
        while True:
            counter += 1
            if counter >= self.retry:
                break
            with aiohttp.Timeout(self.timeout):
                try:
                    response = yield from self.session.get(url, headers=self.headers)
                    body = yield from response.read()
                    break
                except asyncio.TimeoutError as err:
                    logging.warning('Timeout error getting {0}'.format(url))
                    return None
                except Exception:
                    return None
    ...

当它尝试向格式错误的 URL 发出请求时,我收到如下消息:

Future exception was never retrieved
future: <Future finished exception=gaierror(11004, 'getaddrinfo failed')>
Traceback (most recent call last):
  File "H:\Python_3_4_2\lib\concurrent\futures\thread.py", line 54, in run
    result = self.fn(*self.args, **self.kwargs)
  File "H:\Python_3_4_2\lib\socket.py", line 530, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno 11004] getaddrinfo failed

尝试从 session.get 产生响应时发生错误。据我了解,异常从未被 asyncio 消耗,因此它不是“喋喋不休”。

首先我尝试通过 try/except 简单地包装请求:

try:
    response = yield from self.session.get(url, headers=self.headers)
except Exception:
    return None

这不起作用。

然后我 read here 关于链接协程以捕获异常,但这对我也不起作用。一段时间后,我仍然会收到这些消息和脚本崩溃。

所以我的问题 - 我怎样才能以适当的方式处理这个异常?

【问题讨论】:

标签: python exception-handling python-asyncio coroutine aiohttp


【解决方案1】:

不是您问题的答案,但可能是您的问题的解决方案,具体取决于您是否只想让代码正常工作。

我会在请求之前验证 URL。我对这种试图收集一些数据的东西感到很头疼,所以我决定提前修复它们,并将格式错误的 url 报告到日志中。

您可以使用 django 的正则表达式或其他代码来执行此操作,因为它是公开可用的。

在这个问题中,有人给出了 django 的验证正则表达式。 Python - How to validate a url in python ? (Malformed or not)

【讨论】:

  • 是的,我一直在寻找那个方向,但还有其他问题。小型研究表明,并非所有导致此错误的链接都是格式错误的。其中一些只是重定向或 WebSocket 的服务器,而不是 http(s)。我认为在这种情况下最好能够捕获异常。
  • 也许您可以通过此处讨论的方法发布调试回溯:docs.python.org/3/library/… 也许它会提供更多有关确切触发它的信息。不管怎样,祝你好运,维护和继续运行刮板可能是一场噩梦^^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-07
  • 2020-03-17
  • 1970-01-01
  • 2020-11-30
  • 1970-01-01
  • 2017-10-15
  • 1970-01-01
相关资源
最近更新 更多