如何规避Python打开文件数量限制以批量发送目录文件?
解决Python打开过多文件报错
[Errno 24] Too many open files的方案 问题背景
我需要将用户目录下的所有文件内容通过请求发送,但无法修改接收服务,因此不能将文件压缩后发送,必须发送全部文件。文件总大小有限制,但文件数量无限制。然而当尝试打开过多文件时,Python会报错:
[Errno 24] Too many open files。我的当前代码如下:files_to_send = [] files_to_close = [] for file_path in all_files: file_obj = open(file_path, "rb") files_to_send.append(("files", (file_path, file_obj))) files_to_close.append(file_obj) requests.post(url, files=files_to_send) for file_to_close in files_to_close: file_to_close.close()
可行的解决办法
1. 分批次发送文件(优先推荐)
这是最通用、最稳妥的方案——既然一次性打开所有文件会触发限制,那咱们就把文件分成小批量处理,每批只打开有限数量的文件,发送完成后立刻关闭,再处理下一批。这样能严格控制同时打开的文件数,完全在代码层面解决问题,不需要依赖系统设置。
示例代码如下:
import requests # 可根据系统默认限制调整批次大小,比如默认ulimit是1024,设500留足余量 BATCH_SIZE = 500 all_files = [...] # 你的所有文件路径列表 target_url = "你的接收服务URL" # 按批次遍历文件列表 for batch_start in range(0, len(all_files), BATCH_SIZE): batch_files = all_files[batch_start:batch_start + BATCH_SIZE] files_to_send = [] open_files = [] try: # 打开当前批次的文件并准备请求参数 for file_path in batch_files: f = open(file_path, "rb") files_to_send.append(("files", (file_path, f))) open_files.append(f) # 发送请求 response = requests.post(target_url, files=files_to_send) response.raise_for_status() # 可选:检查请求是否成功 print(f"批次{batch_start//BATCH_SIZE +1}发送成功") except Exception as e: print(f"批次{batch_start//BATCH_SIZE +1}处理失败: {str(e)}") finally: # 无论请求成功失败,都确保关闭所有打开的文件 for f in open_files: try: f.close() except Exception: # 忽略关闭时的小错误,避免影响后续流程 pass
2. 临时调整系统文件描述符限制(仅限Unix-like系统)
如果你的运行环境是Linux/macOS,且有足够权限,可以临时提高当前进程的文件描述符上限,让Python能同时打开更多文件。不过这个方法有局限性:Windows系统不支持,且普通用户可能无法修改硬限制,文件数量极多时仍不适用。
示例代码:
import resource # 获取当前的文件描述符限制(软限制/硬限制) soft_limit, hard_limit = resource.getrlimit(resource.RLIMIT_NOFILE) # 设置新的软限制(不能超过硬限制,这里设为4096,可根据需求调整) new_soft_limit = min(4096, hard_limit) resource.setrlimit(resource.RLIMIT_NOFILE, (new_soft_limit, hard_limit)) # 之后再执行你原来的发送代码
3. 流式上传(需接收端支持)
如果接收服务支持流式的multipart/form-data上传,你可以用生成器逐个读取文件内容,不需要一次性打开所有文件。不过这个方法需要你手动构造请求体,实现起来相对复杂,且前提是接收端能兼容这种上传方式(你提到不能修改接收服务,所以需要确认它支持)。
内容的提问来源于stack exchange,提问作者user3715648
相关产品推荐
相关产品推荐

