Python3进程替换场景下子进程无法打开父进程文件描述符问题咨询
问题根因
该差异来自Python 2和Python 3中subprocess.Popen的close_fds参数默认值不同:
- Python 2中
close_fds默认值为False,父进程启动子进程时会继承所有已打开的文件描述符,进程替换生成的文件描述符(示例中的fd 11)会正常传递给argopen子进程,因此可以正常读取内容。 - Python 3中
close_fds默认值为True,父进程启动子进程前会关闭所有除标准输入、标准输出、标准错误之外的文件描述符,进程替换对应的文件描述符在此步骤被关闭,因此子进程访问/proc/self/fd/11时对应的fd已经不存在,触发文件不存在报错。
解决方案
方案1:对齐Python 2默认行为(最简单)
显式指定close_fds=False启动子进程,修改test-process-subst.py的Popen调用逻辑:
from subprocess import Popen import sys Popen(['/home/slu/util/argopen'] + sys.argv[1:], close_fds=False)
该方案适合不需要额外隔离父进程文件描述符的场景,修改量最小。
方案2:显式传递需要的文件描述符(更安全)
如果有安全需求需要保留close_fds=True的隔离特性,可以通过pass_fds参数显式指定要传递给子进程的进程替换对应的文件描述符:
from subprocess import Popen import sys import re pass_fds = [] for arg in sys.argv[1:]: # 匹配进程替换生成的/proc/self/fd路径,提取对应fd编号 fd_match = re.fullmatch(r'/proc/self/fd/(\d+)', arg) if fd_match: pass_fds.append(int(fd_match.group(1))) Popen( ['/home/slu/util/argopen'] + sys.argv[1:], pass_fds=pass_fds )
该方案只会传递需要的进程替换文件描述符,其他无关的父进程fd依然会被关闭,安全性更高。
内容的提问来源于stack exchange,提问作者Steven Lu
相关产品推荐
相关产品推荐

