使用pytest-mpi的--basetemp flag时如何解决FileExistsError?
问题:pytest-mpi中使用--basetemp flag触发FileExistsError的解决方法
错误原因
当用mpirun -n 4启动4个MPI进程运行pytest时,每个进程都会独立执行pytest的初始化流程,包括尝试创建--basetemp指定的out目录。第一个进程成功创建目录后,剩余进程再执行mkdir操作时,就会触发FileExistsError——因为目标目录已存在。
修复方案
方案1:使用pytest-mpi官方适配的mpi_tmp_path fixture
pytest-mpi专门提供了mpi_tmp_path fixture,用于解决MPI多进程下的临时目录冲突:它会自动让rank 0进程创建父目录,同时为每个进程生成独立的子目录,无需手动处理同步逻辑。
修改后的测试代码:
# Standard Library Imports import os # Third-Party Library Imports from mpi4py import MPI import pytest @pytest.mark.mpi() def test_mpi(mpi_tmp_path): MPI_comm: MPI.Intracomm = MPI.COMM_WORLD comm_rank: int = MPI_comm.Get_rank() # 写入进程信息到文件 file_name: str = f"rank_{comm_rank}.txt" file_path: str = os.path.join(mpi_tmp_path, file_name) with open(file_path, "w") as file: file.write(f"{comm_rank}")
运行命令保持不变:
mpirun -n 4 python -m pytest --with-mpi --basetemp=out -v -k test_mpi
方案2:手动通过MPI同步处理目录创建
如果不想使用官方fixture,可以通过MPI的屏障同步机制,让rank 0进程单独创建目录,其他进程等待目录创建完成后再执行操作:
修改后的测试代码:
# Standard Library Imports import os # Third-Party Library Imports from mpi4py import MPI import pytest @pytest.mark.mpi() def test_mpi(tmp_path): MPI_comm: MPI.Intracomm = MPI.COMM_WORLD comm_rank: int = MPI_comm.Get_rank() # 仅让rank 0创建目录,exist_ok=True避免重复创建报错 if comm_rank == 0: os.makedirs(tmp_path, exist_ok=True) # 同步所有进程,确保rank 0完成目录创建后再继续 MPI_comm.Barrier() # 写入进程信息到文件 file_name: str = f"rank_{comm_rank}.txt" file_path: str = os.path.join(tmp_path, file_name) with open(file_path, "w") as file: file.write(f"{comm_rank}")
方案3:不指定--basetemp(简易临时方案)
如果不需要固定临时目录路径,可以去掉--basetemp=out参数,pytest会自动为每个测试运行生成唯一的临时目录,避免进程间的目录冲突。但这种方式不便于后续查看测试生成的文件。
内容的提问来源于stack exchange,提问作者jltorchinsky
相关产品推荐
相关产品推荐

