You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu下Python多线程爬虫报Too many open files [eventpoll]排查求助

嘿,这个问题我之前在多线程爬虫项目里踩过类似的坑!结合你提到的eventpoll条目和跨平台差异,给你几个逐步排查的思路:

1. 优先检查requests Session的复用与关闭逻辑

这是最常见的根源——Linux下文件描述符(FD)的回收机制比Windows更“严谨”,如果每个请求都新建requests.Session或者用完没正确关闭,这些Session持有的网络连接FD会被长期占用,积累到一定数量就触发Too many open files。

  • 建议线程内复用Session:每个线程初始化一个Session,全程复用,线程结束时调用session.close();或者用with上下文管理器确保自动关闭:
    with requests.Session() as session:
        response = session.get(url)
        # 处理响应
    
  • 避免在循环/每个任务里反复创建Session,这会导致大量冗余的连接FD无法及时释放。

2. 排查线程资源泄漏

如果线程没有正常退出,它持有的所有资源(包括网络FD)都不会被回收:

  • 用ps -T -p <你的进程PID>查看线程数量是否持续增长,如果是,说明有僵尸线程或者线程池未正确关闭。
  • 检查你的线程池配置:比如用concurrent.futures.ThreadPoolExecutor时,是否在任务全部完成后调用了executor.shutdown()?或者是否存在无限循环的线程任务没设置退出条件?

3. 验证系统文件描述符限制

Ubuntu默认的进程最大打开文件数可能偏低(通常默认是1024),可以先确认:

  • 用ulimit -n看当前shell的限制,用cat /proc/<你的PID>/limits查看目标进程的实际限制。
  • 如果限制确实太低,可以临时调高(比如ulimit -n 4096)测试,但这只是治标,核心还是要找到泄漏根源,不然调得再高最终还是会爆。

4. 配置requests的连接池参数

requests依赖urllib3的连接池,默认的连接数设置可能导致大量空闲连接占用FD:

  • 显式设置连接池的最大连接数,限制空闲连接的数量:
    from requests.adapters import HTTPAdapter
    
    session = requests.Session()
    # 限制每个域名的连接数
    adapter = HTTPAdapter(pool_connections=10, pool_maxsize=10)
    session.mount('http://', adapter)
    session.mount('https://', adapter)
    
  • 也可以尝试关闭keep-alive来测试:session.get(url, headers={'Connection': 'close'}),如果问题消失,说明是空闲keep-alive连接没被正确回收。

5. 用工具定位FD泄漏点

如果以上思路都没找到问题,可以用工具精准追踪:

  • 用strace -p <你的PID> -e open,close实时查看进程的FD打开/关闭操作,看哪些FD只打开没关闭。
  • 用py-spy top -p <你的PID>分析Python进程的调用栈,观察哪些线程在持续创建网络连接但未释放。
  • 结合lsof -p <你的PID> | grep eventpoll的结果,找到这些FD对应的线程ID,再用pstack <你的PID>查看线程栈,定位到具体的代码逻辑。

最后补充

Windows的FD回收机制更宽松,很多隐性的资源泄漏不会立刻暴露,但Linux下会严格累积,所以跨平台出现差异很正常。优先从Session复用、线程生命周期、连接池配置这几个方向入手,大概率能解决问题。

内容的提问来源于stack exchange,提问作者Susheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:26:31