# ValueError: too many file descriptors in select()错误和解决

本文探讨了asyncio并发爬虫在Windows系统下遇到的ValueError: toomanyfiledescriptorsinselect()错误,详细解释了错误原因,并提供了解决方案,即通过限制并发量使用asyncio.Semaphore来避免超出系统文件描述符限制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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()
<think>好的,我现在需要解决用户遇到的Python错误ValueError: too many values to unpack (expected 2)。首先,我得回忆一下这个错误的常见原因。根据之前的引用资料,这个错误通常发生在解包操作时,期望的变量数量与实际可迭代对象的元素数量不匹配。比如,当用户尝试用两个变量去接收超过两个元素的可迭代对象时,就会触发这个错误。 用户提供的错误代码片段是:for i, col in df.columns[1:-1:2]:。这里可能的问题在于df.columns[1:-1:2]返回的是一个列名的切片,每个元素只是一个列名字符串,而不是包含两个元素的元组或其他结构。所以,当循环试图将每个列名解包到icol两个变量时,就会失败,因为每个列名只是一个值,无法分解为两个部分。这时候,应该只用一个变量来接收每个列名,而不是尝试解包。 接下来,我需要检查可能的解决方法。根据引用[3]中的建议,首先应该检查可迭代对象的长度。比如,在循环之前,可以打印出df.columns[1:-1:2]的内容,看看里面每个元素的结构。如果每个元素确实是单个值,那么循环变量应该只有一个,而不是两个。 另外,引用[2]提到,可能需要调整解包变量的数量。比如,在示例代码中,用户错误地使用了icol来迭代单个元素,应该改为只用一个变量,比如col,或者如果确实需要索引,可以使用enumerate函数来同时获取索引列名。例如,for i, col in enumerate(df.columns[1:-1:2]): 这样每个元素就会被正确解包为icol。 此外,引用[4]提到在加载模型时遇到类似错误,但用户的问题出现在数据处理阶段,所以可能需要排除其他情况。不过,基本思路是一致的:检查解包时的变量数量是否匹配。 总结起来,用户需要做的是检查循环中的可迭代对象的结构,确保每个元素的数量与解包变量数量一致。可能的解决方案包括调整循环变量数量,或使用enumerate等函数生成索引。同时,添加调试语句查看实际的数据结构也是关键步骤。</think>### ValueError: too many values to unpack (expected 2) 解决方案 #### **错误原因** 此错误表示尝试将包含多个值的可迭代对象解包到数量不匹配的变量中。例如,当使用 `for i, col in iterable` 时,若 `iterable` 中的每个元素**不是二元组**(或包含两个元素的结构),则会触发此错误。 --- #### **具体分析与解决方法** ##### **1. 检查可迭代对象的元素结构** 假设原始代码如下: ```python for i, col in df.columns[1:-1:2]: # 报错位置 ... ``` - **问题**:`df.columns` 返回的是列名的索引对象(如 `Index([&#39;col1&#39;, &#39;col2&#39;, ...], dtype=&#39;object&#39;)`),切片后的每个元素仅为一个列名字符串,无法解包为 `i` `col` 两个变量。 - **验证方法**: ```python print(df.columns[1:-1:2].tolist()) # 输出类似 [&#39;col2&#39;, &#39;col4&#39;, ...] ``` ##### **2. 调整解包变量数量** - **直接迭代列名**(单变量接收): ```python for col in df.columns[1:-1:2]: print(col) # 直接使用列名 ``` - **需要索引时使用 `enumerate`**: ```python for i, col in enumerate(df.columns[1:-1:2]): print(i, col) # i 是索引,col 是列名 ``` ##### **3. 其他场景的修复方法** - **解包函数返回值**:若函数返回多个值但未对齐变量数: ```python # 错误示例 a, b = func_return_three_values() # 函数返回 (1, 2, 3) # 正确示例 a, b, c = func_return_three_values() ``` - **字典遍历时的键值对**: ```python # 错误示例(遍历字典的键) for key, value in my_dict: # 错误!应使用 my_dict.items() # 正确示例 for key, value in my_dict.items(): ``` --- #### **示例修复代码** 针对用户提供的代码: ```python #错误代码 for i, col in df.columns[1:-1:2]: # 处理列 # 修复方法1:仅迭代列名 for col in df.columns[1:-1:2]: print(col) # 修复方法2:使用 enumerate 获取索引 for idx, col in enumerate(df.columns[1:-1:2]): print(f"第{idx}列: {col}") ``` --- #### **总结步骤** 1. **检查可迭代对象**:打印或调试确认元素的真实结构。 2. **调整变量数量**:确保解包变量数与元素数量一致。 3. **使用辅助函数**:如 `enumerate()` 或 `zip()` 对齐结构。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值