ValueError: too many file descriptors in select()的原因
因为asyncio内部用到了select,而select就是系统打开文件数是有限度的,,这个其实是操作系统的限制,linux打开文件的最大数默认是1024,windows默认是509,超过了这个值,程序就开始报错,
下面的代码一次性将处理url的函数作为任务扔进了一个超大的List中,这就引起了错误。
我最初出错在于windows系统中asyncio爬虫测试中:
import aiohttp
import asyncio
num = 0
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main(url):
async with aiohttp.ClientSession() as session:
html = await fetch(session, url)
global num
num += 1
print('------------{}'.format(num))
# print(html)
#asyncio 高并发库
def tasks():
task = list()
for i in range(114499,120000):
# 114499 http://blog.jobbole.com/114499/
task.append(main("http://blog.jobbole.com/{}/".format(i)))
return task
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks()))
解决:
如下面的代码。限制并发量, semaphore = asyncio.Semaphore(500) async with semaphore:
#Windows在500以下。
#coding:utf-8
import time,asyncio,aiohttp
#aiohttp则是基于asyncio实现的HTTP框架。
#asyncio 协程并发模块
num = 0
async def fetch(session,url):
async with session.get(url) as response: #session.get(url)获取页面
return await response.text() #返回页面解码后的信息
async def main(url,semaphore):
async with semaphore: #这里进行执行asyncio.Semaphore,
async with aiohttp.ClientSession() as session: 创建了一个命名为session的aiohttp.ClientSession 对象
html = await fetch(session, url) #相当于 yield from
global num
num += 1
print(html)
print('------------{}'.format(num))
async def run():
semaphore = asyncio.Semaphore(500) # 限制并发量为500,这里windows需要进行并发限制,
#不然将报错:ValueError: too many file descriptors in select()
to_get = [main("http://blog.jobbole.com/{}/".format(_),semaphore) for _ in range(114364,120000)]
#总共1000任务
await asyncio.wait(to_get)
#Python中对于无需关注其实际含义的变量可以用_代替,这就和for i in range(5)一样,因为这里我们对i并不关心,所以用_代替仅获取值而已。
if __name__ == '__main__':
# now=lambda :time.time()
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()