处理aiohttp中的错误请求

时间:2019-05-14 14:19:18

标签: python python-asyncio aiohttp

我正在尝试找到一种方法来使用aiohttp处理异步函数中来自API的错误请求。这是我要测试的:

async def fetch(session):
    url = 'http://httpbin.org/status/404'
    async with session.request('GET', url) as response:
        if response.status == 200:
            try:
                r = await response.json()
                return r
            except ValueError:
                return
        else:
            return None

async def fetch_all(project_list):
    output = []
    async with ClientSession() as session:
        tasks = [asyncio.ensure_future(fetch(session, project)) for project in project_list]
        for future in await asyncio.gather(*tasks):
            output += future
    return output

def get_data(project_list):
    loop = asyncio.get_event_loop()
    futures = asyncio.ensure_future(fetch_all(project_list))
    output = loop.run_until_complete(futures)
    return output

在此示例中,project_list只是一个整数列表。

在这种情况下,fetch()应该不返回任何值,因为响应无疑是404。问题发生在fetch_all()中,我将其告知未来+=。我得到一个TypeError: 'coroutine' object is not iterable.基本上我不希望它返回任何内容,在这种情况下,该列表中没有+=的内容。在理想情况下,我每次都会收到适当的json响应,但是我想考虑一个随机实例,其中我从服务器收到了错误的响应。

根据我的阅读,@asyncio.coroutine将返回None,但如果我正确理解,则async的值必须为awaited

2 个答案:

答案 0 :(得分:1)

首先,如果要使用collect,则无需将任务包装在sure_future中。其次,您尝试添加带有2个参数的访存任务:session和project,但是在访存函数定义中只有session。您还可以更改的另一件事是删除循环,在该循环中循环访问收集结果,因为它已经为您提供了要返回的输出。 代码将是这样的:

async def fetch(session, project):
    url = 'http://httpbin.org/status/404'
    async with session.request('GET', url) as response:
        if response.status == 200:
            try:
                return await response.json()

            except ValueError:
                pass

        return None

async def fetch_all(project_list):
    output = []
    async with ClientSession() as session:
        tasks = [fetch(session, project) for project in project_list]
        return await asyncio.gather(*tasks)

def get_data(project_list):
    loop = asyncio.get_event_loop()
    output = loop.run_until_complete(futures)
    return output

有关建议:仅当您想立即运行协程时才使用sure_future,但仅在将来需要使用结果。

答案 1 :(得分:0)

我不确定这是最好的方法,但我将其放在一起并成功了。如果有人可以纠正我,请这样做。

async def fetch_all(project_list):
    output = []
    async with ClientSession() as session:
        tasks = [asyncio.ensure_future(fetch(session, project)) for project in project_list]
        for future in await asyncio.gather(*tasks):
            if future is not None: #Check if the future is None before adding it
                output += future
    return output