循环正确处理keybreak异常时中断



我需要实现一个函数,该函数监视正在运行的作业的状态,直到作业完成。类似这样的东西:

def monitor_job(job_id):
ended = False
while not ended:
ended = check_if_ended(job_id)
time.sleep(5)
print('ended')

现在,我想允许用户使用Ctrl-C中断循环,在这种情况下,我想优雅地停止调用stop_job()函数的作业。然而,这个函数是异步的,它只是提交一个停止作业的请求,这可能需要一些时间才能完成。因此,在这个调用之后,我想继续while循环,等待作业结束。这里有一个尝试:

def monitor_job(job_id):
keybreaks = False
ended = False
while not ended:
# (...)
try:
ended = check_if_ended(job_id)
time.sleep(5)
except KeyboardInterrupt:
# break after a second keybreak
if keybreaks:
raise
keybreaks = True
stop_job(job_id)
print('ended')

在这个解决方案中,我不喜欢的是,如果碰巧在try之外(例如在(...)处(触发Ctrl-C,那么异常将不会被捕获,作业也不会正常停止。

有没有一个好的方法来正确处理这个问题,避免这种时间问题

我想到了一些解决方案,比如:在except块中复制while循环,这并不优雅;或者将try置于while循环之外,然后在except中回调monitor_job(),但随后Ctrl-C可能在函数调用期间发生。

确实有可能Ctrl-C发生在(...)。但它只是一个非常小机会。

如果你想绝对确定,你可以使用以下片段:

def monitor_job(job_id, first_call=True):
ended = False
try:
if first_call:
monitor_job(job_id, first_call=False)
while not ended:
ended = check_if_ended(job_id)
time.sleep(5)
except KeyboardInterrupt:
if first_call:
raise

它还使用了类似您所建议的递归,但不是在except块中,而是在try块中。因此,当您点击Ctrl-C时,首先退出对monitor_job(first_call=False)的内部调用,只有在第二个Ctrl-C之后才退出外部函数。

这是我能想出的最优雅的解决方案。

相关内容

  • 没有找到相关文章

最新更新