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)
这两种方法在范围、安全性和可用性方面的优缺点是什么?有没有更好的办法?
嗯,一如既往,这取决于。
正如您可能已经验证的那样,这两种方法都有效。我想说这取决于您的应用程序和正确的实现(您的信号方法有点错误......)
如果正确实施,这两种方法都可以被认为是“安全的”。这取决于 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,您的线程最终会注意到这一点并退出。
不过,我可能会选择您的多处理并加入。
汉努