#python #aiohttp
#python #aiohttp
Вопрос:
Я только начал с aiohttp и столкнулся с проблемой, которую, похоже, не могу разгадать.
Я создаю постоянный сеанс.
session = aiohttp.ClientSession(headers=headers)
async def fetch(url):
async with session.get(url) as resp:
return await resp.json()
async def run():
task = asyncio.create_task(fetch('https://someurl'))
await task
При вызове run()
моя программа вылетает со следующей трассировкой.
RuntimeError: Timeout context manager should be used inside a task
Я не получаю никакой обратной трассировки, и функция выполняется нормально, когда я не использую постоянный сеанс. То есть, run
выполняется, как ожидалось, когда я определяю fetch
следующим образом.
async def fetch(url):
async with aiohttp.ClientSession(headers=headers) as see:
async with session.get(url) as resp:
return await resp.json()
Комментарии:
1.
def run
нетasync
, поэтому вы не можете использоватьawait
внутри него. Возможно, форматирование post неверно?2. Да, я пропустил
async
ключевое слово при публикации вопроса. Я внес изменения в свой исходный пост.
Ответ №1:
Вам нужно будет перейти session = ...ClientSession
внутрь fetch
, также было бы лучше использовать async with
при создании сеанса.
Что-то вроде
async def fetch(url):
async with aiohttp.ClientSession(headers=headers) as session:
async with session.get(url) as resp:
return await resp.json()
async def run():
task = asyncio.create_task(fetch('https://someurl'))
await task
Обновленный, более полный пример:
class Foboar():
def __init__(self):
self.session = None
async def run(self):
self.session = aiohttp.ClientSession(headers=headers)
try:
for url in all_my_urls:
await self.fetch(url)
finally:
await self.session.close()
async def fetch(self, url):
async with self.session.get(url) as resp:
return await resp.json()
Комментарии:
1. Это работает, но в конечном итоге я создаю новый сеанс для каждого выполняемого запроса. Как я могу сохранить сеанс для повторного использования, а не создавать новый сеанс при каждом вызове
fetch
2. да, поэтому создайте сеанс в
run
и передавайте его каждомуfetch
вызову. Посмотрите на основной пример здесь .3. Согласно docs.aiohttp.org/en/stable /… диспетчер контекста сеанса не требуется, что я и делаю. Более того, предлагаемый вами подход по-прежнему создает новый сеанс при каждом вызове
run
. Я хочу создать дляsession
каждого сайта что-то вроде инициализацииself.session = aiohttp.ClientSession()
при инициализации моего HttpClient.4. извините, я спешил, обновился более полным примером реализации
self.session
.5. Чем это отличается от моего первоначального вопроса? После
run
вызова,self.session
будет привязан к экземпляруaiohttp.ClientSession
и в моем коде я привязываюсьsession
кaiohttp.ClientSession
перед вызовомrun
. Единственный способ заставить мой код работать — это пройтиtimeout=None
, но увидеть другие проблемы.