Python asyncio:错误是我还是API?

2024-09-30 06:12:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用支持异步的第三方API包装器。由于我是asyncio新手,我很难弄清楚如何使用它,而且我不确定我遇到的错误是我的用法(很可能是)还是包装器本身

API可以在这里找到:https://clashroyale.readthedocs.io/en/latest/api.html#royaleapi

我的代码的目标是一次发出三个API请求(.get_clan(*lClanGroup)),异步而不是同步

我的代码:

import clashroyale
import asyncio
import aiohttp

# Define Tokens
unofficialAPIToken = "secretToken"

# Get Client Objects
session1 = aiohttp.ClientSession()
unofficialClient = clashroyale.royaleapi.Client(unofficialAPIToken, session=session1, is_async=True)

lClanGroups = ['PPCLCJG9', '2LRU2J', 'PGLQ0VQ', 'YU2RQG9', '2LVRQ29'],['PYP8UPJV', 'P9L0CYY0', 'Y2RGQPJ', '8P2GYJ8', '9VQJPL2L'],['RYPRGCJ', '809R8PG8', 'PJY9PP98', '2GCQLC', '2GL2QPPL']

async def x(lClanGroup):
    print(*lClanGroup)
    a = await unofficialClient.get_clan(*lClanGroup) # Iterates five tags for the API to request at once
    return a

async def y(lClanGroups):
    result = await asyncio.gather(x(lClanGroups[0]),x(lClanGroups[1]),x(lClanGroups[2]))
    return result

async def close_sessions():
    await session1.close()

asyncio.run(y(lClanGroups))
asyncio.run(close_sessions())

我遇到的错误很长,很难理解:

C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\Scripts\python.exe C:/Users/Adam/PycharmProjects/ClashRoyaleMeta/testme2.py
PPCLCJG9 2LRU2J PGLQ0VQ YU2RQG9 2LVRQ29
PYP8UPJV P9L0CYY0 Y2RGQPJ 8P2GYJ8 9VQJPL2L
RYPRGCJ 809R8PG8 PJY9PP98 2GCQLC 2GL2QPPL
C:/Users/Adam/PycharmProjects/ClashRoyaleMeta/testme2.py:16: DeprecationWarning: The object should be created from async function
  session1 = aiohttp.ClientSession()
Traceback (most recent call last):
  File "C:/Users/Adam/PycharmProjects/ClashRoyaleMeta/testme2.py", line 33, in <module>
    asyncio.run(y(lClanGroups))
  File "C:\Program Files\Python38\lib\asyncio\runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "C:\Program Files\Python38\lib\asyncio\base_events.py", line 612, in run_until_complete
    return future.result()
  File "C:/Users/Adam/PycharmProjects/ClashRoyaleMeta/testme2.py", line 27, in y
    result = await asyncio.gather(x(lClanGroups[0]),x(lClanGroups[1]),x(lClanGroups[2]))
  File "C:/Users/Adam/PycharmProjects/ClashRoyaleMeta/testme2.py", line 23, in x
    a = await unofficialClient.get_clan(*lClanGroup)
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\clashroyale\royaleapi\client.py", line 203, in _aget_model
    raise e
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\clashroyale\royaleapi\client.py", line 196, in _aget_model
    data, cached, ts, resp = await self._request(url, **params)
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\clashroyale\royaleapi\client.py", line 150, in _arequest
    async with self.session.get(url, timeout=timeout, headers=self.headers, params=params) as resp:
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\aiohttp\client.py", line 1012, in __aenter__
    self._resp = await self._coro
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\aiohttp\client.py", line 426, in _request
    with timer:
  File "C:\Users\Adam\PycharmProjects\ClashRoyaleMeta\venv2\lib\site-packages\aiohttp\helpers.py", line 579, in __enter__
    raise RuntimeError('Timeout context manager should be used '
RuntimeError: Timeout context manager should be used inside a task
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x0000016C5AD50EB0>

Process finished with exit code 1

谢谢你的帮助


Tags: inpyclientasyncioaiohttpliblineawait
1条回答
网友
1楼 · 发布于 2024-09-30 06:12:41

每个asyncio.run()创建新的event loop。此外,如果全局创建像aiohttp.ClientSession()这样的对象,它们可能会绑定到默认事件循环

在程序中使用多个事件循环是危险的,可能会导致不明显的问题。为了避免这种情况:

  • 只运行asyncio.run()一次
  • 在主协同程序中创建所有与asyncio相关的内容

我没有使用royaleapi,但似乎API开发人员在tests中做的事情与您不同。这是他们如何innit/close stuff和他们如何get clan

让我们试一试吧

import clashroyale
import asyncio


TOKEN = "secretToken"

clan_groups = [
    ['PPCLCJG9', '2LRU2J', 'PGLQ0VQ', 'YU2RQG9', '2LVRQ29'],
    ['PYP8UPJV', 'P9L0CYY0', 'Y2RGQPJ', '8P2GYJ8', '9VQJPL2L'],
    ['RYPRGCJ', '809R8PG8', 'PJY9PP98', '2GCQLC', '2GL2QPPL']
]


async def get_clans(cr, clan_groups):
    return await asyncio.gather(*[
        cr.get_clan(tag)
        for group in clan_groups
        for tag in group
    ])


async def main():
    cr = clashroyale.RoyaleAPI(
        TOKEN, 
        is_async=True,
        timeout=30
    )
    try:
        results = await get_clans(cr, clan_groups)
        print(results)
    finally:
        await cr.close()
        await asyncio.sleep(2)

asyncio.run(main())

没有测试它

相关问题 更多 >

    热门问题