Python中仅重定向子进程stdout至文件失效问题求助
问题描述
parent.py:
from mpi4py import MPI import sys comm = MPI.COMM_WORLD for i in range(10): print(something) child_comm = MPI.COMM_WORLD.Spawn(sys.executable, args=['child.py'], maxprocs=9) child_comm.Disconnect()
child.py:
import sys sys.stdout = open("analysis_log.txt", "a") # 运行求解器相关代码 sys.stdout.close()
需求是仅重定向child.py的输出(求解器底层为Fortran编译代码,通过Fortran的write/print语句输出内容),但通过修改sys.stdout或contextlib.redirect_stdout均无法生效,而终端重定向>>却可以正常工作。请问如何解决该问题?为什么会出现这种差异?
Python版本:3.8.13
原因分析
Python的sys.stdout仅负责处理Python层面的输出流,而Fortran编译的二进制代码直接操作的是系统级别的标准输出文件描述符(file descriptor),二者不属于同一层级。终端重定向>>是操作系统层面的操作,会直接修改整个进程的标准输出文件描述符,因此能覆盖Python和Fortran的所有输出。
解决方案
方案1:Spawn子进程时通过MPI参数指定重定向
在调用MPI.Spawn时,通过info参数设置系统级的输出重定向,无需修改child.py即可覆盖所有语言的输出:
修改parent.py中的Spawn调用:
from mpi4py import MPI import sys comm = MPI.COMM_WORLD info = MPI.Info.Create() # 设置stdout和stderr追加到日志文件 info.Set("stdout", "analysis_log.txt") info.Set("stderr", "analysis_log.txt") info.Set("append", "1") # 启用追加模式 for i in range(10): print(something) child_comm = MPI.COMM_WORLD.Spawn( sys.executable, args=['child.py'], maxprocs=9, info=info ) child_comm.Disconnect() info.Free()
方案2:在child.py中修改系统文件描述符
直接操作系统级文件描述符,替换stdout/stderr的指向,覆盖所有输出流:
修改child.py:
import os # 打开日志文件,获取文件描述符(O_CREAT确保文件不存在时创建) log_fd = os.open("analysis_log.txt", os.O_WRONLY | os.O_APPEND | os.O_CREAT) # 将stdout(1)和stderr(2)的文件描述符替换为日志文件的fd os.dup2(log_fd, 1) os.dup2(log_fd, 2) # 关闭原文件描述符 os.close(log_fd) # 运行求解器相关代码
方案3:通过Shell命令实现重定向
利用Shell的重定向功能,在Spawn时直接调用Shell执行命令:
修改parent.py中的Spawn调用:
child_comm = MPI.COMM_WORLD.Spawn( 'bash', args=['-c', f'{sys.executable} child.py >> analysis_log.txt 2>&1'], maxprocs=9 )
内容的提问来源于stack exchange,提问作者Pavan
相关产品推荐
相关产品推荐

