Skip to main content
 首页 » 编程设计

Python subprocess.Popen()之子进程导致套接字保持打开状态

2025年05月04日28zhengyun_ustc

我有一个 Python2.7 脚本,它执行了一些并行魔法并最终进入 Flask gui_loop。在某个时刻,一个线程使用 subprocess.Popen 创建一个后台进程。这行得通。

当我的脚本退出并且子进程仍在运行时,我无法再次运行我的脚本,因为 flask gui_loop 失败并显示:

socket.error: [Errno 98] Address already in use 

使用 netstat -peanut 我可以看到当 python 脚本退出时套接字的所有权转移到子进程。这是 python 脚本和子进程都在运行时的样子:

root@test:/tmp# netstat -peanut | grep 5000 
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN      1000       840210      21458/python     

终止 Python 脚本后,socket 不会关闭,但其所有权已传递给子进程:

root@test:~/PycharmProjects/foo/gui# netstat -peanut | grep 5000 
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN      1000       763103      19559/my-subprocess 

有什么办法解决这个问题吗?子进程(用 C 语言编写)没有在该套接字上执行任何操作,也不需要它。我能否以某种方式创建一个子进程而不将 gui 循环套接字资源传递给它?

我当然可以终止进程,但这并不理想,因为这样做的目的是围绕一些计算构建一个简单的 gui,并且如果 gui 脚本恰好退出则不会丢失进度。如果我可以启动并再次运行 gui 脚本,我将有一种机制来重新连接到子进程。

R

请您参考如下方法:

你应该使用 close_fds=True在创建子进程时,这将导致在子进程中关闭所有文件描述符(以及因此打开的套接字)(stdin/stdout/stderr 除外)。

在较新的版本(python 3.2+)中,close_fds 已经默认为 True,因为在大多数情况下您不想继承子进程中所有打开的文件描述符, 但在 python2.7 中你仍然需要明确指定它。