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

Windows下Python多进程TCP客户端偶发创建失败问题求助

Windows下Python多进程传递Socket引发的不稳定进程创建问题

问题描述

在Windows 10 + Python 3.11.2环境下,搭建了如下架构:

  • TCP服务器通过新线程处理 incoming connections,listen的backlog设置为200
  • 另一个进程通过multiprocessing.Process创建大量TCP客户端进程连接服务器

但客户端进程创建不稳定:有时5个就出错,有时150个正常运行,部分进程创建失败,报错如下:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 120, in spawn_main 
    exitcode = _main(fd, parent_sentinel)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 130, in _main      
    self = reduction.pickle.load(from_parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\reduction.py", line 238, in _rebuild_socket
    return ds.detach()
           ^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\resource_sharer.py", line 38, in detach
    with _resource_sharer.get_connection(self._id) as conn:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\resource_sharer.py", line 86, in get_connection
    c = Client(address, authkey=process.current_process().authkey)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\connection.py", line 499, in Client    c = PipeClient(address)
        ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\erath\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\connection.py", line 701, in PipeClient
    _winapi.WaitNamedPipe(address, 1000)
FileNotFoundError: [WinError 2] Das System kann die angegebene Datei nicht finden

问题原因

Windows平台下Python的多进程默认使用spawn启动方式:

  1. spawn模式会启动一个全新的Python解释器进程,而非类Unix系统的fork方式
  2. 父进程需要将传递给子进程的对象序列化(pickle),子进程再反序列化重建对象
  3. 对于Socket这类操作系统级资源,序列化时依赖multiprocessing.resource_sharer通过**命名管道(Named Pipe)**共享文件描述符
  4. 当父进程短时间内创建大量子进程时,命名管道的创建/初始化速度跟不上子进程启动节奏,或者父进程的资源共享服务被抢占,导致子进程尝试连接命名管道时找不到资源,抛出FileNotFoundError

解决方案

最可靠的修复方式是不在父进程创建Socket传递给子进程,而是让每个子进程自行创建Socket,彻底避免跨进程传递操作系统资源的问题。

修改后的客户端代码:

import socket
import multiprocessing
import time

MAX_DATASIZE = 2048
HOST = "127.0.0.1"
PORT = 5000

def handleSingleConnection(i):
    # 子进程内部创建Socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((HOST, PORT))
    time.sleep(2)
    sock.sendall(f"Hello from Process {i}!".encode())
    result = sock.recv(MAX_DATASIZE)
    print(result)
    sock.close()

if __name__ == '__main__':
    processes = []
    for i in range(150):
        process = multiprocessing.Process(target=handleSingleConnection, args=(i,))
        process.start()
        processes.append(process)
    
    # 可选:等待所有子进程结束,避免父进程提前退出导致资源泄漏
    for p in processes:
        p.join()

额外优化建议

  1. 父进程通过join()等待所有子进程完成,避免父进程提前终止引发资源清理异常
  2. 若需要控制并发连接数,可使用进程池(multiprocessing.Pool)替代循环创建进程,避免短时间内创建过多进程引发系统资源竞争

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:44:53