在Python中正确地设置代码超时执行的方法
我在网上查了一下,发现有一些讨论和ActiveState的做法,关于如何在代码运行时设置超时。看起来有几种常见的方法:
- 使用线程来运行代码,然后用
join
方法加上超时。如果超时了,就杀掉这个线程。不过,这种方法在Python中并不直接支持(用了私有的_Thread__stop
函数),所以这被认为是不好的做法。 - 使用
signal.SIGALRM
- 但这种方法在Windows上不管用! - 使用子进程并设置超时 - 但这太重了,如果我想经常启动可以中断的任务,我可不想每次都启动一个新进程!
那么,什么才是正确的方法呢?我不是在问变通的方法(比如使用Twisted和异步IO),而是想知道解决实际问题的真正方法 - 我有一个函数,想要在设定的超时时间内运行。如果超时了,我想要控制权返回。而且我希望这个方法在Linux和Windows上都能用。
10 个回答
6
如果是网络相关的问题,你可以试试:
import socket
socket.setdefaulttimeout(number)
12
你可能在寻找的是 multiprocessing 模块。如果 subprocess
对你来说太复杂了,那么这个模块可能也不太适合你。
import time
import multiprocessing
def do_this_other_thing_that_may_take_too_long(duration):
time.sleep(duration)
return 'done after sleeping {0} seconds.'.format(duration)
pool = multiprocessing.Pool(1)
print 'starting....'
res = pool.apply_async(do_this_other_thing_that_may_take_too_long, [8])
for timeout in range(1, 10):
try:
print '{0}: {1}'.format(duration, res.get(timeout))
except multiprocessing.TimeoutError:
print '{0}: timed out'.format(duration)
print 'end'
12
其实,这个问题没有一个通用的解决办法。你得根据具体情况来选择合适的解决方案。
如果你想给自己完全控制的代码设置超时,你需要让代码能够配合工作。这段代码必须能够以某种方式分成小块,就像在事件驱动的系统中那样。如果你能确保没有任何东西会长时间占用锁,也可以通过多线程来实现,但处理锁其实挺复杂的。
如果你想设置超时是因为你担心代码失控(比如,你担心用户会让你的计算器计算
9**(9**9)
),那么你需要在另一个进程中运行它。这是唯一一个简单的方法来确保它的隔离。把它放在你的事件系统里或者甚至是另一个线程里都不够安全。虽然也可以像之前那样把代码分成小块,但这需要非常小心的处理,通常也不值得;而且,这样做也不能完全做到和直接运行Python代码一样的效果。