Python实验脚本异常:最后一个实验environment.cfg未转移且删除失败
问题分析与解决:多重复实验中environment.cfg未转移导致崩溃
核心问题
运行多重复实验时,程序完成实验后需将文件移至新文件夹以启动下一轮,但最后一个实验的environment.cfg文件未被正常转移/删除,引发程序崩溃;手动运行相同代码却无异常。
问题根源
- 文件句柄未释放:代码中直接用
open()打开文件后未显式关闭,导致文件被进程占用,无法删除或移动。 - 子进程操作冗余:
proc.communicate()已等待Avida进程结束,后续的proc.terminate()属于冗余操作,可能导致资源残留。 - 文件删除未做存在性检查:直接调用
remove('./environment.cfg'),若文件因占用未生成或已被占用,会触发异常。 - 资源释放不及时:Avida进程结束后,系统可能未及时释放
data文件夹或environment.cfg的资源,导致后续移动/删除操作失败。
修复方案
1. 用with语句管理文件句柄
确保文件自动关闭,避免占用:
# 读取environment.cfg时替换为: with open(f'./experiment_{num}/environment.cfg', 'r') as env_file: env_file_content = [line.split(' ') for line in env_file] # 写入environment.cfg时替换为: with open(f'./experiment_{num}/environment.cfg', 'w') as out: for i in range(n): out.write(f'RESOURCE res{i}:inflow={var0}:outflow={var1}\n') sc=0 for i in range(n): out.write(f'REACTION reaction{i} {reactiontype[sc]} process:resource=res{i}:value={reward[sc]}:min={var3}\n') sc += 1 if sc == len(reactiontype): sc = 0
2. 移除冗余的子进程终止操作
删除proc.terminate(),因为proc.communicate()已等待进程完成并回收资源。
3. 增加文件删除的存在性检查
避免因文件不存在触发异常:
import os # 替换原有的remove语句: if os.path.exists('./environment.cfg'): os.remove('./environment.cfg')
4. 添加短暂延时确保资源释放
在Avida进程结束后,给系统时间释放资源:
proc = subprocess.Popen(['./avida'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = proc.communicate() # 添加延时 time.sleep(1)
5. 优化实验文件夹移动逻辑
确保所有文件操作完成后再移动文件夹,可在移动前检查源文件夹是否存在:
source = f'./experiment_{numb}' dest = f'./replicate_{replicatenum}/experiment_{numb}' if os.path.exists(source): shutil.move(source, dest)
修改后的关键代码片段
if exptype == 1: for ex in range(expnum): num = ex + 1 mkdir(f'experiment_{num}') copy('./default_files/environment.cfg', f'./experiment_{num}/environment.cfg') # 读取配置文件(用with自动关闭) with open(f'./experiment_{num}/environment.cfg', 'r') as env_file: env_file_content = [line.split(' ') for line in env_file] n = num var0 = '100' var1 = '0.01' var3 = '1' reactiontype = ['not','nand','and','orn','or','andn','nor','xor','equ'] reward = ["1.0","1.0","2.0","2.0","4.0","4.0","8.0","8.0","16.0"] # 写入配置文件(用with自动关闭) with open(f'./experiment_{num}/environment.cfg', 'w') as out: for i in range(n): out.write(f'RESOURCE res{i}:inflow={var0}:outflow={var1}\n') sc=0 for i in range(n): out.write(f'REACTION reaction{i} {reactiontype[sc]} process:resource=res{i}:value={reward[sc]}:min={var3}\n') sc += 1 if sc == len(reactiontype): sc = 0 # 运行Avida copy(f'./experiment_{num}/environment.cfg', './') print(f"starting experiment_{num}") proc = subprocess.Popen(['./avida'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = proc.communicate() # 增加延时确保资源释放 time.sleep(1) shutil.move('./data', f'./experiment_{num}') # 检查文件存在后再删除 if os.path.exists('./environment.cfg'): os.remove('./environment.cfg')
内容的提问来源于stack exchange,提问作者Zydrarc
相关产品推荐
相关产品推荐

