在给定的时间后杀死函数?

Ann*_*nna 7 python multithreading signal-processing timer

在 Python 中给定时间后终止函数(仍在运行)的最佳方法是什么?这是我目前发现的两种方法:

说这是我们的基本功能:

import time
def foo():
    a_long_time = 10000000
    time.sleep(a_long_time)

TIMEOUT = 5 # seconds
Run Code Online (Sandbox Code Playgroud)

1. 多处理方法

import multiprocessing

if __name__ == '__main__':
    p = multiprocessing.Process(target=foo, name="Foo")
    p.start()

    p.join(TIMEOUT)

    if p.is_alive()
        print('function terminated')
        p.terminate()
        p.join()
Run Code Online (Sandbox Code Playgroud)

2. 信号方法

import signal

class TimeoutException(Exception):
    pass

def timeout_handler(signum, frame):
    raise TimeoutException

signal.signal(signal.SIGALRM, timeout_handler)


signal.alarm(TIMEOUT)    
try:
    foo()
except TimeoutException:
    print('function terminated')
Run Code Online (Sandbox Code Playgroud)

这两种方法在范围、安全性和可用性方面的优缺点是什么?有没有更好的办法?

Han*_*nnu 5

嗯,一如既往,这取决于。

正如您可能已经验证的那样,这两种方法都有效。我想说这取决于您的应用程序和正确的实现(您的信号方法有点错误......)

如果正确实施,这两种方法都可以被认为是“安全的”。这取决于 foo 函数之外的主程序是否需要执行某些操作,或者它是否可以只是等待 foo 完成或超时。信号方法不允许任何并行处理,因为您的主程序将在 foo() 中运行,直到完成或超时。但你需要消除信号。如果您的 foo 一秒钟内完成,您的主程序将离开 try/ except 结构,四秒后... kaboom ... 会引发异常并且可能未被捕获。不好。

try:
    foo()
    signal.alarm(0)
except TimeoutException:
    print ("function terminated")
Run Code Online (Sandbox Code Playgroud)

解决了问题。

我个人更喜欢多处理方法。它更简单,并且不需要信号和异常处理,理论上,如果在发出信号时程序执行不是您期望的位置,那么理论上可能会出错。如果您的程序可以在 join() 中等待,那么您就完成了。但是,如果您想在等待时在主进程中执行某些操作,则可以进入循环,跟踪变量中的时间,检查是否超时,如果超时,则终止进程。您只需使用带有微小超时的 join 来“查看”进程是否仍在运行。

另一种方法是使用带有类或全局变量的线程,具体取决于您的 foo()。如果你的 foo 继续处理命令而不是可能等待很长时间才能完成命令,你可以在那里添加一个 if 子句:

def foo():
    global please_exit_now
    while True:
        do_stuff
        do_more_stuff
        if foo_is_ready:
            break
        if please_exit_now is True:
            please_exit_now = False
            return 
    finalise_foo
    return 
Run Code Online (Sandbox Code Playgroud)

如果 do_stuff 和 do_more_stuff 在合理的时间内完成,您就可以在主程序中处理事情,只需将全局 please_exit_now 设置为 True,您的线程最终会注意到这一点并退出。

不过,我可能会选择您的多处理并加入。

汉努