Python 无法捕获ctrl+;运行mpi4py时使用c

Python 无法捕获ctrl+;运行mpi4py时使用c,python,openmpi,mpi4py,Python,Openmpi,Mpi4py,我一直在使用一个代码来处理~9000个文件中的一些数据,因为每个进程都需要一些时间,所以我设法使用mpi4py来加速它。但是我不能让程序捕捉ctrl+c信号并保存已经计算的结果。代码如下: import os import sys from string import atof import gc import pandas as pd import numpy as np from StructFunc.Structure_Function import SF_true, SF_fit_par

我一直在使用一个代码来处理~9000个文件中的一些数据,因为每个进程都需要一些时间,所以我设法使用mpi4py来加速它。但是我不能让程序捕捉ctrl+c信号并保存已经计算的结果。代码如下:

import os
import sys
from string import atof
import gc
import pandas as pd
import numpy as np
from StructFunc.Structure_Function import SF_true, SF_fit_params
import scipy.io as sio
import mpi4py
from mpi4py import MPI
import time
import signal



# def handler(signal_num, frame):

#   combine_list = comm.gather(p, root=0)

#   if comm_rank == 0:
#       print combine_list
#       combine_dict = {}
#       for sub_dict in combine_list:
#           for cur_key in sub_dict.keys():
#               combine_dict[cur_key] = sub_dict[cur_key]
#   print combine_dict
#   sio.savemat('./all_S82_DRW_params.mat', combine_dict)
#   print "results before the interrupt has been saved."
#   sys.exit()


# signal.signal(signal.SIGINT, handler)


comm = MPI.COMM_WORLD
comm_rank = comm.Get_rank()
comm_size = comm.Get_size()


bad_value = [-1, -99.99, -1]

lc_path = '/Users/zhanghaowen/Desktop/AGN/BroadBand_RM/QSO_S82'

model="DRW"



if comm_rank == 0:

    file_list = os.listdir(lc_path)
    # print file_list
    sys.stderr.write('%d files were to be processed.' %len(file_list))


file_list = comm.bcast(file_list if comm_rank == 0 else None, root=0)
num_files = len(file_list)
# num_files = 6
local_files_offset = np.linspace(0, num_files, comm_size+1).astype('int')
local_files = file_list[local_files_offset[comm_rank] : local_files_offset[comm_rank + 1]]
sys.stderr.write('%d/%d processor gets %d/%d data' %(comm_rank, comm_size, len(local_files), num_files))
cnt = 0

p = {}

for ind, lc in enumerate(local_files):
    # beginning of process
    try:
        print local_files[ind]
        lc_file = open(os.path.join(lc_path, local_files[ind]), 'r')
        lc_data = pd.read_csv(lc_file, header=None, names=['MJD', 'mag', 'err'], usecols=[0, 1, 2], sep=' ')
        lc_file.close()

        #remove the bad values in the data

        lc_data['MJD'] = lc_data['MJD'].replace(to_replace=bad_value[0], value=np.nan)
        lc_data['MJD'] = lc_data['MJD'].replace(to_replace=np.nan, value=np.nanmean(lc_data['MJD']))

        lc_data['mag'] = lc_data['mag'].replace(to_replace=bad_value[1], value=np.nan)
        lc_data['mag'] = lc_data['mag'].replace(to_replace=np.nan, value=np.nanmean(lc_data['mag']))

        lc_data['err'] = lc_data['err'].replace(to_replace=bad_value[2], value=np.nan)
        lc_data['err'] = lc_data['err'].replace(to_replace=np.nan, value=np.nanmean(lc_data['err']))

        MJD = np.array(lc_data['MJD'])
        mag = np.array(lc_data['mag'])
        err = np.array(lc_data['err'])

        SF_params = []

        resamp_tag = 0
        while resamp_tag < 1:
            sim_err = np.array([abs(np.random.normal(0, err[i], size=1)) for i in range(len(err))]).reshape((1, len(err)))[0]

            try:
                p[lc] = SF_fit_params(MJD, mag, sim_err, MCMC_step=100, MCMC_threads=1, model=model)
                cnt += 1
                sys.stderr.write('processor %d has processed %d/%d files \n' %(comm_rank, cnt, len(local_files)))
                print "finished the MCMC for %s \n" %lc
                resamp_tag += 1
            except:
                continue
    # end of process


    except KeyboardInterrupt:
        combine_list = comm.gather(p, root=0)

        if comm_rank == 0:
            print combine_list
            combine_dict = {}
            for sub_dict in combine_list:
                for cur_key in sub_dict.keys():
                    combine_dict[cur_key] = sub_dict[cur_key]
            print combine_dict

        sio.savemat('./all_S82_DRW_params.mat', combine_dict)
        print "save the dict."
        os._exit()



combine_list = comm.gather(p, root=0)

if comm_rank == 0:
    print combine_list
    combine_dict = {}
    for sub_dict in combine_list:
        for cur_key in sub_dict.keys():
            combine_dict[cur_key] = sub_dict[cur_key]
    print combine_dict

    sio.savemat('./all_S82_DRW_params.mat', combine_dict)
导入操作系统
导入系统
从字符串导入atof
导入gc
作为pd进口熊猫
将numpy作为np导入
从StructFunc.Structure_函数导入SF_true、SF_fit_参数
将scipy.io作为sio导入
导入mpi4py
从mpi4py导入MPI
导入时间
输入信号
#def处理器(信号数量,帧):
#combine_list=comm.gather(p,root=0)
#如果comm_rank==0:
#打印联合收割机列表
#combine_dict={}
#对于组合列表中的子目录:
#对于子目录键()中的当前键:
#组合指令[当前键]=子指令[当前键]
#打印合并记录
#sio.savemat('./所有图纸参数mat',组合目录)
#打印“保存中断前的结果”
#sys.exit()
#signal.signal(signal.SIGINT,handler)
comm=MPI.comm_WORLD
通信等级=通信获取等级()
通信大小=通信获取大小()
错误的_值=[-1,-99.99,-1]
lc_path='/Users/zhanghaowen/Desktop/AGN/BroadBand_RM/QSO_S82'
model=“DRW”
如果comm_rank==0:
file\u list=os.listdir(lc\u路径)
#打印文件列表
sys.stderr.write(“%d个文件要处理”。%len(文件列表))
file_list=comm.bcast(如果comm_秩=0,则为file_list,否则为None,根=0)
num\u files=len(文件列表)
#num_files=6
local\u files\u offset=np.linspace(0,num\u files,comm\u size+1).astype('int')
本地文件=文件列表[本地文件偏移量[通信等级]:本地文件偏移量[通信等级+1]]
sys.stderr.write(“%d/%d个处理器获取%d/%d个数据“%”(comm_秩、comm_大小、len(本地_文件)、num_文件))
cnt=0
p={}
对于枚举中的ind、lc(本地_文件):
#过程的开始
尝试:
打印本地_文件[ind]
lc_file=open(os.path.join(lc_path,local_files[ind]),'r')
lc_data=pd.read_csv(lc_文件,头=None,名称=['MJD','mag','err'],usecols=[0,1,2],sep='')
lc_file.close()
#删除数据中的错误值
lc_数据['MJD']=lc_数据['MJD'].replace(to_replace=bad_值[0],value=np.nan)
lc_数据['MJD']=lc_数据['MJD'].replace(to_replace=np.nan,value=np.nanmean(lc_数据['MJD']))
lc_数据['mag']=lc_数据['mag'].replace(to_replace=bad_值[1],value=np.nan)
lc_数据['mag']=lc_数据['mag'].replace(to_replace=np.nan,value=np.nanmean(lc_数据['mag']))
lc_数据['err']=lc_数据['err'].replace(to_replace=bad_值[2],value=np.nan)
lc_数据['err']=lc_数据['err'].replace(to_replace=np.nan,value=np.nanmean(lc_数据['err']))
MJD=np.数组(lc_数据['MJD'])
mag=np.数组(lc_数据['mag'])
err=np.array(lc_数据['err'])
SF_参数=[]
重新映射标记=0
当重新映射标签<1时:
模拟错误=np.数组([abs(np.random.normal(0,err[i],size=1)),用于范围内的i(len(err))))。重塑((1,len(err)))[0]
尝试:
p[lc]=SF_拟合参数(MJD、mag、sim_误差、MCMC_步长=100、MCMC_线程=1、模型=model)
cnt+=1
sys.stderr.write('处理器%d已处理%d/%d个文件\n'(通信秩、cnt、len(本地文件)))
打印“已完成%s的MCMC\n”%lc
重新映射标记+=1
除:
持续
#进程结束
除键盘中断外:
combine_list=comm.gather(p,root=0)
如果comm_rank==0:
打印联合收割机列表
combine_dict={}
对于组合列表中的子目录:
对于子目录键()中的当前键:
组合指令[当前键]=子指令[当前键]
打印合并记录
sio.savemat('./所有图纸参数mat',组合目录)
打印“保存记录”
操作系统(u exit)
combine_list=comm.gather(p,root=0)
如果comm_rank==0:
打印联合收割机列表
combine_dict={}
对于组合列表中的子目录:
对于子目录键()中的当前键:
组合指令[当前键]=子指令[当前键]
打印合并记录
sio.savemat('./所有图纸参数mat',组合目录)
我尝试了两种捕获ctrl+c信号的方法,即我定义但注释的处理函数和except键盘中断技巧。当我使用
python all.py
运行代码,然后键入ctrl+c时,脚本将捕获信号,但在保存结果后继续运行;当我使用
mpirun-np 2 all.py
并键入ctrl+c时,脚本会停止而不保存

我认为在MPI模式下的问题可能是只有manager进程捕捉到了信号,但是为什么在我键入ctrl+c后,单个进程没有在非MPI模式下停止?有人知道如何让工作进程捕捉到信号并在终止之前做些什么吗


顺便说一句,我正在使用openmpi。

关于管理器在mpi模式下接收ctrl-c的说法,您可能是对的。它将始终转到连接到终端/键盘的进程,该进程可能是管理器。另外,捕获中断后脚本继续的原因是您没有告诉它不要这样做。触发
except
子句后,执行通常会在
try
/
except
块下方继续。如果要强制程序终止,可以在
块中包括
exit()
,但
除外。在mpi的情况下,经理应该向工人发送一条消息,告诉他们在此时终止。谢谢你的建议。但是我在except块中尝试了exit()、sys.exit()和os.\u exit(),但它们都不起作用……我猜问题在于内部循环中的catch all
except:
子句(带有
resamp\u标记的那一个)。如果用户在该循环中按下ctrl-c,它将被内部的
except
子句捕获并被忽略。如果那不是问题的话,你能做一个mor吗