import asyncio


async def _gather_with_concurrency(n, *tasks):
    """Limits open files to avoid 'too many open files' error

    Parameters
    ------
        n (int): number of files to open at once

    Returns
    ------
        awaitable: gathered coroutines that need to awaited

    Notes
    ------
        https://stackoverflow.com/questions/48483348/how-to-limit-concurrency-with-python-asyncio/61478547#61478547
    """
    semaphore = asyncio.Semaphore(n)

    async def sem_task(task):
        async with semaphore:
            return await task
    return await asyncio.gather(*(sem_task(task) for task in tasks))