我正在运行python脚本中的fortran代码,有时需要一段时间才能运行。因此,我使用this link:
中的代码来限制运行时间def timeout(func, args=(), kwargs={}, timeout_duration=15, default=1):
import signal
class TimeoutError(Exception):
pass
def handler(signum, frame):
raise TimeoutError()
# set the timeout handler
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout_duration)
try:
result = func(*args, **kwargs)
except TimeoutError as exc:
result = default
finally:
signal.alarm(0)
return result
我基本上将另一个函数(部分在下面)放到这个(上面)中来运行fortran代码:
subprocess.check_output('./../bin/SPhenoUMSSM ../UMSSM/LH_out_'+mod+' > SPheno_log_'+mod, shell=True)
但是我意识到,当fortran代码占用超过15秒(这是超时函数的边界)时,它会留在内核中并在for循环中执行另一个代码,这会在我的内核中创建转储。为了防止这种情况,我想使用subprocess.popen()
,因为它给了我pid来终止核心中的作业,但是我需要等待进程执行,就像subprocess.check_output()
那样。因此,如果有一种方法可以将popen和check_output属性结合起来,等到15秒内完成作业,并且它不仅仅是终止它,那么我很感兴趣。
答案 0 :(得分:1)
这不是世界上最复杂的代码,但它可能很有用。
import subprocess, time
x = subprocess.Popen(['sleep', '15'])
polling = None
i = 0
while polling == None:
time.sleep(1)
polling = x.poll()
i +=1
if i > 15: break
if polling == None:
try:
x.kill()
print "Time out - process terminated" # process terminated by kill command
except OSError:
print "Process completed on time" # process terminated between poll and kill commands
except Exception as e:
print "Error "+str(e) # kill command failed due to another exception "e"
else:
print "Process Completed after "+str(i)+" seconds"
编辑:杀人问题似乎无法正常运作
尝试使用os.kill(x.pid, signal.SIGKILL)
而不是SIGTERM
我相信SIGTERM
要求流程干净地关闭,而不是立即终止。不知道是什么驱动了fortran脚本,很难知道终止信号的作用。也许代码正在做点什么
例如:
如果我按如下方式运行shell脚本:
#!/bin/bash
trap "echo signal" 15
sleep 30
并发送它kill -15 pid_number
,它将不会打印“信号”,直到睡眠在30秒后终止,而如果我发出kill -9 pid_number
它将立即终止而没有打印出来。
简短的回答是,我不知道,但我怀疑答案在于运行fortran代码的脚本。
编辑:
注意:为了成功运行x.kill()
或os.kill()
或subprocess.call('kill '+ str(x.pid), shell=True)
,x中的shell
选项需要为False。因此可以使用
import shlex
args = shlex.split(ARGS HERE)
x = subprocess.Popen(args) # shell=False is default
但是请注意,如果您想使用... >& log_file
将输出写入日志文件,它将不起作用,因为>&
不是脚本的有效参数,而是您的shell环境。因此,只需要使用对python运行的脚本有效的参数。
答案 1 :(得分:0)
check_output上有一个超时参数,只需将其设置为15秒。
try:
subprocess.check_output(['arg1', 'arg2'], timeout=15)
except:
print("Timed out")
此处的文档https://docs.python.org/3/library/subprocess.html#subprocess.check_output
check_output也会返回输出,所以如果你关心它,只需存储结果。
还有一个等待功能对于更复杂的用例非常有用。 check_output和wait阻止,直到进程结束,或者直到达到超时。
答案 2 :(得分:0)
上面的一个补充答案,shell也有一个内部超时命令,因此可以按如下方式使用;
timeout <TIME IN SEC> ./blabla > log_file
我在python中使用它如下;
try:
check_output('timeout --signal=SIGKILL 12 ./<COMMAND> > log', shell=True)
flag = 0
except:
flag = 1
因此,可以检查标志是1还是0以了解作业发生了什么。请注意,如果--signal=SIGKILL
终止,则Killed
在运行结束时写入kill -l
。如需更多信号选项,可以查看 axios.defaults.baseURL='http://localhost:4000/';
。