gpt4 book ai didi

python - 在类 __init__ 上定义 aiohttp ClientSession 以供以后重用

转载 作者:行者123 更新时间:2023-12-05 07:02:41 25 4
gpt4 key购买 nike

我想创建一个持续到程序结束的持久 session ,我有以下代码。

import asyncio
import aiohttp
import atexit

class Session:
def __init__(self):
self._session = aiohttp.ClientSession()
atexit.register(self._close_session)

async def get(self, url):
response = await self._session.request("GET", url)
return await response.json()

def _close_session(self):
asyncio.run(self._session.close())


async def pullit():
print(await session.get("https://raw.communitydragon.org/latest/game/data/characters/aatrox/aatrox.bin.json"))

session = Session()

asyncio.run(pullit()) # THIS THROWS: Timeout context manager should be used inside a task
asyncio.get_event_loop().run_until_complete(pullit()) #THIS RUNS OK

这在 self._session.request 行上引发了一个异常,Timeout context manager should be used inside a task,我已经搜索了其他答案,但它仍然给出同样的错误。

问题:这个错误的原因是什么?如果我想打开一个持续程序生命周期的 session ,并且我需要在类中定义它(强制性),那会怎样?

额外: 目前我正在使用 atexit 在程序结束时关闭 session (引用上面的代码),这是一个好的方式吗这样做?如果不是,什么是更好的做法

更新:我找到了解决方案,它是使用 asyncio.get_event_loop().run_until_complete(...),但不是 asyncio.run() 和上面一样吗?为什么一个运行没有问题而 3.7+ asyncio.run() 不运行?


更新 2:我得到了以下代码:

#runner.py
import aiohttp
import asyncio


class Runner:
def __init__(self, coro):
self.coro = coro

async def run(self):
session = aiohttp.ClientSession()
client.start_session(session)
await self.coro
client.close_session()
await session.close()


def run(coro):
runner = Runner(coro)
return asyncio.run(runner.run())
#client.py
class Client:
def __init__(self):
self._session = None

async def get(self, url):
response = await self._session.request("GET", url)
return await response.json()

def start_session(self, session):
self._session = session

def close_session(self):
self._session = None
from .runner import run
from .client import Client

client = Client()

async def pullit():
print(await client.get("https://raw.communitydragon.org/latest/game/data/characters/aatrox/aatrox.bin.json"))

run(pullit())

好的,这一切都运行了,但在它运行之后它抛出了我RuntimeError: Event loop is closed,我从来没有关闭过一个循环。

最佳答案

这是我对你的问题的解决方案:

import aiohttp
import asyncio
import atexit


class HTTPClient():
def __init__(self):
self._session = aiohttp.ClientSession()
atexit.register(self._shutdown)
print('session created')

async def request(self, *args, **kwargs):
async with self._session.request(*args, **kwargs) as response:
return (response.status, await response.text())

def _shutdown(self):
asyncio.run(self._session.close())
print('session closed')


async def main():
http_client = HTTPClient()
status, text = await http_client.request(url='http://example.com', method='GET')
print(status)


asyncio.run(main())

另一方面,我想,最好的方法应该是对以下代码进行一些包装:

async with aiohttp.ClientSession() as session:
# perform all needed http calls inside
pass

关于python - 在类 __init__ 上定义 aiohttp ClientSession 以供以后重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63471158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com