一个任务
有必要启动几个会话并让每个会话执行一定数量的请求。我想指出,有必要有几个会话,而不仅仅是一个,正如几乎所有 aiohttp 示例中所展示的那样。下面是其中的代码:
- 通过循环运行 curutina运行
- 在运行中创建了 3 个会话,并且将创建的会话和加载列表转移到相同数量的任务 ( runfetchers ) 中
- 每个runfetchers每个会话运行 20 次提取。
- 下载后,应将所有结果收集在一个地方,并关闭打开的会话。
问题
- 我刚开始了解 asyncio \ aiohttp ,也许我想错了,请纠正我。
- 代码正在运行,但是在关闭打开的会话时发生错误(因为我还没有尝试过)
在此之前,我尝试通过一个会话完成所有操作,并且一切正常,因为我使用了使用上下文管理器的示例中的代码,它本身关闭了会话,并且在示例中使用了一层“沉浸式” .
编码
import asyncio
import aiohttp
import math
# генератор который будет разрезать списки
def listpartial(inlist, n):
if n > 0:
s = math.ceil(len(inlist) / n)
for q in range(s):
yield inlist[q * n:(q + 1) * n]
# собсвенно загрузчик страниц
async def fetch(num, session):
try:
url = f'https://en.wikipedia.org/wiki/{num}'
async with session.get(url) as r:
await asyncio.sleep(0.1, 0.3)
return await r.text(encoding='utf-8')
except Exception as e:
print('fetch', e)
return ''
async def runfetchers(numlist, session):
tasks2 = []
# создам количество задач на загрузку каждого элемента
for num in numlist:
task = asyncio.ensure_future(fetch(num, session))
tasks2.append(task)
responses = await asyncio.gather(*tasks2)
return responses
async def run(allnums):
tasks = []
sessions = []
# получии объект генератор который будет выдавать списки по 20 элементов
numlist = listpartial(allnums, 20)
# создам 3 сессии и столько же задач и запущу их
for _ in range(3):
session = aiohttp.ClientSession()
sessions.append(session)
task = asyncio.ensure_future(runfetchers(next(numlist), session))
tasks.append(task)
responses = await asyncio.gather(*tasks)
# закрываю открытые сессии
# ?????? как закрыть вот эти сессии
# for i in sessions:
# sessions[i].close()
return responses
if __name__ == '__main__':
nums = [x for x in range(1200)]
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(nums))
res = loop.run_until_complete(future)
print(res)
结论
下面给出了我的问题的答案(再次感谢),但同时我编写了一个以不同方式解决我的问题的代码,也许它对某人会派上用场:
# собсвенно загрузчик страниц
async def fetch(num, session):
try:
url = f'https://en.wikipedia.org/wiki/{num}'
async with session.get(url) as r:
await asyncio.sleep(0.1, 0.3)
return await r.text(encoding='utf-8')
except Exception as e:
print('fetch', e)
return ''
# запустим сессию, которая запустит несколько запросов
# и потом сама себя закроет
async def start_sesssion(numlst):
async with aiohttp.ClientSession() as session:
futs = [asyncio.create_task(fetch(n, session)) for n in numlst]
return await asyncio.gather(*futs)
if __name__ == '__main__':
nums = [x for x in range(1200)]
numlist = listpartial(nums, 20)
loop = asyncio.get_event_loop()
futures = [loop.create_task(start_sesssion(next(numlist))) for i in range(3)]
result = loop.run_until_complete(asyncio.gather(*futures))
print(result)
ClientSession.close()是一个协程,所以
或者