通过 python 在时间范围内终止程序
Terminating a program within a time frame through python
我正在 运行 从 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 秒内完成,如果它不只是终止它。
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 returns 输出也是如此,所以如果您关心它,只需存储结果即可。
还有一个等待函数,可用于更复杂的用例。 check_output 和 wait 都会阻塞,直到进程完成或达到超时。
这不是世界上最复杂的代码,但它可能很有用。
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"
编辑:kill 似乎没有起作用的问题。
尝试使用 os.kill(x.pid, signal.SIGKILL)
而不是 SIGTERM
.
我相信 SIGTERM
要求进程彻底关闭,而不是立即终止。不知道是什么驱动了 fort运行 脚本,就很难知道终止信号的作用。也许代码正在做一些事情。
例如:
如果我 运行 一个 shell 脚本如下:
#!/bin/bash
trap "echo signal" 15
sleep 30
并发送它 kill -15 pid_number
,它不会打印 "signal" 直到睡眠在 30 秒后终止,而如果我发出 kill -9 pid_number
它会立即终止而不会打印任何内容。
简短的回答是,我不知道,但我怀疑答案就在 运行 堡垒 运行 代码的脚本中。
编辑:
注意:为了成功 运行 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 运行s.
脚本有效的参数
对上述问题的补充回答,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
.
我正在 运行 从 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 秒内完成,如果它不只是终止它。
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 returns 输出也是如此,所以如果您关心它,只需存储结果即可。
还有一个等待函数,可用于更复杂的用例。 check_output 和 wait 都会阻塞,直到进程完成或达到超时。
这不是世界上最复杂的代码,但它可能很有用。
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"
编辑:kill 似乎没有起作用的问题。
尝试使用 os.kill(x.pid, signal.SIGKILL)
而不是 SIGTERM
.
我相信 SIGTERM
要求进程彻底关闭,而不是立即终止。不知道是什么驱动了 fort运行 脚本,就很难知道终止信号的作用。也许代码正在做一些事情。
例如:
如果我 运行 一个 shell 脚本如下:
#!/bin/bash
trap "echo signal" 15
sleep 30
并发送它 kill -15 pid_number
,它不会打印 "signal" 直到睡眠在 30 秒后终止,而如果我发出 kill -9 pid_number
它会立即终止而不会打印任何内容。
简短的回答是,我不知道,但我怀疑答案就在 运行 堡垒 运行 代码的脚本中。
编辑:
注意:为了成功 运行 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 运行s.
对上述问题的补充回答,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
.