asyncio中的最大并发数

2020-05-07  本文已影响0人  飞跑的蛤蟆

最近在使用异步并发库写爬虫时,遇到了一个错误ValueError: too many file descriptors in select(),这个错误大概是select使用了太多的文件描述符

查了查资料,发现asyncio中有用到select,而select是系统IO多路复用的一种方式,它会限制单个进程打开文件描述符的数量(linux是1024个,window是509个),如果超出这个值程序就会报错

下面是报错的代码(节选):

...
async def request():
    url = 'http://127.0.0.1:5000'
    print('Waiting for ', url)
    result = await get(url)
    print('Get response from ', url, 'Result: ', result)


def main():
    loop = asyncio.get_event_loop()
    tasks = [asyncio.ensure_future(request()) for _ in range(1000)]
    loop.run_until_complete(asyncio.wait(tasks))
...

代码解析:
main函数中创建了1000个任务对象,然后将这些任务对象以awaitable对象的形式注入到事件循环中,接下来事件循环会调用之前的协程对象。这些代码看似没有问题,但是创建任务对象时创建的太多了,远超出了系统的限制。

解决方案:

asyncio.Semaphore类是同步装置,用于限制并发请求
async with 则是异步上下文管理器

semaphore = asyncio.Semaphore(500)

async def request():
    async with semaphore:
        url = 'http://127.0.0.1:5000'
        result = await get(url)
上一篇 下一篇

猜你喜欢

热点阅读