【问题标题】:How to fix - TypeError: object StreamReader can't be used in 'await' expression如何修复 - TypeError: object StreamReader can't be used in 'await' expression
【发布时间】:2022-01-07 13:40:06
【问题描述】:

我正在使用 python(3.8.8) aiohttp 和 asyncio 来发出异步 http 请求。 但是,当我尝试等待对 resp.content 的调用时,我会收到 TypeError: object StreamReader can't be used in 'await' expression

Traceback (most recent call last):
  File "test_aiohttp.py", line 34, in get_country_wrapper
    country_lst = await asyncio.gather(*result)
  File "test_aiohttp.py", line 17, in get_country
    html_text = await resp.content
TypeError: object StreamReader can't be used in 'await' expression

但是当我尝试等待调用 resp.json() 时,它可以工作。

async def get_country(session, url):
    '''
        Return the country of a given kaggle user
    '''    
    async with session.get(url) as resp:
        # json_resp = await resp.json()
        html_text = await resp.content
        country = re.search(r',"country":"([\w ]+)"', html_text)
        return str(country.group(1))



async def get_country_wrapper(usernames):

    try:
        async with aiohttp.ClientSession() as session:
            
            base_url = 'https://www.kaggle.com/'
            result = []
            for username in usernames:
                url = base_url+str(username)
                result.append(asyncio.create_task(get_country(session, url)))

            country_lst = await asyncio.gather(*result)
            return country_lst

    except Exception as e:
        print("Error: ", traceback.format_exc())


# Below is a sample list of users.
# Actual requirement is to run below for about 10,000 or more users
user_list = ['jhovey1', 'jsheppard95', 'dudihgustian', 'khmx5200', 'skshivamkedia']
asyncio.run(get_country_wrapper(user_list[:5]))

为什么我不能在这里使用像 resp.json() 这样的 resp.content?

(我使用 resp.content 而不是 resp.json() 的原因是后者给这个特定的 url 带来了错误)

我在下面的文章中引用了上面描述的 resp.json() 的用法。

https://www.twilio.com/blog/asynchronous-http-requests-in-python-with-aiohttp

https://itqna.net/questions/76711/error-requests-aiohttp-asyncio

【问题讨论】:

    标签: python python-asyncio aiohttp


    【解决方案1】:

    ClientResponse.json 是一个协程,它尝试将响应数据解析为 JSON 并返回一个字典。 ClientResponse.contentStreamReader 对象用户读取响应数据。这两者不可互换。您可能需要ClientResponse.text 将响应数据作为字符串返回,或者ClientResponse.bytes 将响应数据返回一个字节。

    html_text = await resp.text()
    

    【讨论】:

    • 非常感谢@dirn。现在我得到了错误。 Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000001A6C5BCF790> Traceback (most recent call last): File "\Anaconda3\lib\asyncio\proactor_events.py", line 116, in __del__ self.close() File "\asyncio\proactor_events.py", line 108, in close self._loop.call_soon(self._call_connection_lost, None) File "\asyncio\base_events.py", line 719, in call_soon self._check_closed() File "\asyncio\base_events.py", line 508, in _check_closed raise RuntimeError('Event loop is closed')
    • 知道可能是什么原因吗?下面是编辑后的代码async def get_country(session, url): ''' Return the country of a given kaggle user ''' async with session.get(url) as resp: html_text = await resp.text() country = re.search(r',"country":"([\w ]+)"', html_text) if country != None: country_ = str(country.group(1)) print(country_) return country_ else: return "NA"
    • 评论并不是真正分享这样的代码的地方。你最好问一个新问题。虽然我怀疑如果你从用户名循环 (result.append(get_country(session, url))) 中删除 create_task 调用,你会得到一个更容易阅读的错误。
    • 对不起@dirn 对不起,因为我是这里的新手。顺便说一句,我发现使用 asyncio.get_event_loop().run_until_complete(main()) 而不是 asyncio.run(main()) 解决了这个问题(在上面的评论中提到)。
    猜你喜欢
    • 2022-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    相关资源
    最近更新 更多