aiohttp asyncio.TimeoutError из None с использованием ClientSession

Это странная ошибка, поскольку, когда я пытаюсь ее поймать, она ничего не печатает.

Я использую сервер sanic для asyncio.gather нескольких изображений одновременно, более 3 тысяч изображений.

У меня нет этой ошибки при работе с меньшим размером выборки.

Упрощенный пример:

from sanic import Sanic
from sanic import response
from aiohttp import ClientSession

from asyncio import gather

app = Sanic()

@app.listener('before_server_start')
async def init(app, loop):
    app.session = ClientSession(loop=loop)

@app.route('/test')
async def test(request):
    data_tasks = []
    #The error only happened when a large amount of images were used
    for imageURL in request.json['images']:
        data_tasks.append(getRaw(imageURL))
    await gather(*data_tasks)
    return response.text('done')

async def getRaw(url):
    async with app.session.get(url) as resp:
        return await resp.read()

Что это может быть за ошибка? Если это какое-то ограничение моего хоста/интернета, как мне его избежать?

Я использую базовую каплю от DigitalOcean с 1 vCPU и 1 ГБ RAM, если это поможет.

Ошибка полного стека:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/sanic/app.py", line 750, in handle_request
    response = await response
  File "server-sanic.py", line 53, in xlsx
    await gather(*data_tasks)
  File "/usr/lib/python3.5/asyncio/futures.py", line 361, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 274, in result
    raise self._exception
  File "/usr/lib/python3.5/asyncio/tasks.py", line 241, in _step
    result = coro.throw(exc)
  File "server-sanic.py", line 102, in add_data_to_sheet
    await add_img_to_sheet(sheet, rowIndex, colIndex, val)
  File "server-sanic.py", line 114, in add_img_to_sheet
    image_data = BytesIO(await getRaw(imgUrl))
  File "server-sanic.py", line 138, in getRaw
    async with app.session.get(url) as resp:
  File "/usr/local/lib/python3.5/dist-packages/aiohttp/client.py", line 690, in __aenter__
    self._resp = yield from self._coro
  File "/usr/local/lib/python3.5/dist-packages/aiohttp/client.py", line 277, in _request
    yield from resp.start(conn, read_until_eof)
  File "/usr/local/lib/python3.5/dist-packages/aiohttp/client_reqrep.py", line 637, in start
    self._continue = None
  File "/usr/local/lib/python3.5/dist-packages/aiohttp/helpers.py", line 732, in __exit__
    raise asyncio.TimeoutError from None
concurrent.futures._base.TimeoutError

person Mojimi    schedule 05.02.2019    source источник
comment
Ваши задачи потребляют вашу полосу пропускания.   -  person yorodm    schedule 05.02.2019
comment
@yorodm Я думаю, это довольно сложно ограничить через python, должен ли я просто ограничить максимальное количество одновременных подключений?   -  person Mojimi    schedule 05.02.2019
comment
Можете ли вы проверить ответы здесь и посмотреть, подходят ли они вам?   -  person yorodm    schedule 05.02.2019
comment
@yorodm Я думаю, этого может быть достаточно ? Ограничение размера пула в aiohttp   -  person Mojimi    schedule 05.02.2019


Ответы (1)


Нет смысла запускать миллион запросов одновременно. Ограничьте его до 10 или сколько угодно и дождитесь их, прежде чем продолжить цикл.

for imageURL in request.json['images']:
    data_tasks.append(getRaw(imageURL))
    if len(data_tasks) > 10:
        await gather(*data_tasks)
        data_tasks = []        
await gather(*data_tasks)
person Craftables    schedule 10.02.2019
comment
Это имеет смысл! Как вы считаете, этого варианта от aiohttp достаточно? docs.aiohttp.org/en/stable/ - person Mojimi; 11.02.2019