鍍金池/ 問答/Python  網(wǎng)絡(luò)安全/ 在用 Sanic 的時候 報錯 TypeError coroutine obje

在用 Sanic 的時候 報錯 TypeError coroutine object is not iterable

在用 sanic 做一個小項目的時候, 碰到上面這個問題。這是其中一個 views:

@app.route("/query_video/", methods=["GET"])
async def video_query_views(request: Request):
    keyword = request.args.get("keyword", None)
    page = request.args.get("page", None)
    order = request.args.get("order", None)
    query_params = dict()
    if keyword:
        query_params['keyword'] = keyword
    else:
        return json("keyword can't be empty", status=403)
    if page:
        query_params['page'] = page
    if order:
        query_params['order'] = order
    try:
        rest = dict()
        rest['bilibili'] = await get_bilibili_query(**query_params)
        rest['qq'] = await get_v_qq_query(**query_params)
        rest['youku'] = await get_youku_query(**query_params)
        rest['iqiyi'] = await get_iqiyi_query(**query_params)
        rest['mg'] = await get_mgtv_query(**query_params)
    except Exception as e:
        print(traceback.format_exc())
        return json(str(e), status=403)
    return json(rest)
    

其中g(shù)et_bilibili_query, get_v_qq_query之類的都是一個aiohttp 寫小爬蟲,具體:

async def get_bilibili_query(keyword, page=1, order='tolalrank'):
    base_url = "https://search.bilibili.com/all"
    query_params = {
        "keyword": keyword,
        "page": page,
        "order": order,
    }
    async with aiohttp.ClientSession() as session:
        html = await fetch(session, url=base_url, params=query_params)
    html = etree.HTML(html)
    lis = html.xpath("http://li[@class='video matrix ']")
    rst = list()
    for li in lis:
        try:
            a = li.xpath('a')[0]
            img = a.xpath('div/img')[0]

            time_len = a.xpath('div/span/text()')[0].strip()
            title = a.xpath("@title")[0].strip()
            origin_url = urljoin(base_url, a.xpath('@href')[0].strip())
            img_url = urljoin(base_url, img.xpath("@data-src")[0].strip())
            rst.append({
                'origin_url': origin_url,
                'time_len': time_len,
                'img_url': img_url,
                'title': title
            })
        except Exception:
            continue
    else:
        return rst
        

報錯在 fetch 函數(shù)中:

async def fetch(session, url, **kwargs):
    with async_timeout.timeout(10):
        async with session.get(url, **kwargs, verify_ssl=False) as response:
            return await response.text()

具體錯誤如下:

Traceback (most recent call last):
  File "/Users/angelo/PycharmProjects/pp3/s1.py", line 51, in video_query_views
    rest['iqiyi'] = await get_iqiyi_query(**query_params)
  File "/Users/angelo/PycharmProjects/pp3/sp.py", line 25, in get_bilibili_query
    html = await fetch(session, url=base_url, params=query_params)
  File "/Users/angelo/PycharmProjects/pp3/sp.py", line 13, in fetch
    async with session.get(url, **kwargs, verify_ssl=False) as response:
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/client.py", line 690, in __aenter__
    self._resp = yield from self._coro
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/client.py", line 267, in _request
    conn = yield from self._connector.connect(req)
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/connector.py", line 402, in connect
    proto = yield from self._create_connection(req)
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/connector.py", line 748, in _create_connection
    _, proto = yield from self._create_direct_connection(req)
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/connector.py", line 831, in _create_direct_connection
    req=req, client_error=client_error)
  File "/Users/angelo/PycharmProjects/env3.5/lib/python3.5/site-packages/aiohttp/connector.py", line 796, in _wrap_create_connection
    return (yield from self._loop.create_connection(*args, **kwargs))
TypeError: 'coroutine' object is not iterable

感覺錯誤 報的很奇怪,當(dāng)我直接用 aiohttp 的 web 執(zhí)行的時候,是沒有問題的,直接 loop 執(zhí)行也沒有問題。只有 sanic 執(zhí)行的時候會報錯,但報錯是在aiohttp 中報的。

loop = asyncio.get_event_loop()
    loop.run_until_complete(get_bilibili_query(keyword='python'))

這么執(zhí)行時不會報錯。
求助。。。。

回答
編輯回答
魚梓

在Python3.5以后,原生協(xié)程不能用于迭代,未被裝飾的生成器不能yield from一個原生協(xié)程

2017年2月4日 19:54