我在线查看了一些SO讨论和ActiveState配方,用于运行一些超时的代码。看起来有一些常见的方法:
join
。如果超时已超时 - 终止该线程。这不是Python直接支持的(使用私有_Thread__stop
函数)因此不良做法 signal.SIGALRM
- 但此方法无法在Windows上运行!那么,正确的方式是什么?我不是在询问有关变通方法(例如使用Twisted和async IO),而是解决实际问题的实际方法 - 我有一些功能,我想只运行一些超时。如果超时,我想要控制回来。我希望它能在Linux和Windows上运行。
答案 0 :(得分:9)
您可能正在寻找的是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'
答案 1 :(得分:9)
这个的完全通用解决方案真的,老实说不存在。您必须为给定的域使用正确的解决方案。
如果您希望完全控制代码超时,则必须将其编写为合作。这样的代码必须能够以某种方式分解成小块,就像在事件驱动的系统中一样。你也可以通过线程来做到这一点,如果你可以确保没有任何东西会锁定太长时间,但是处理锁定实际上非常困难。
如果你想要超时,因为你害怕代码失控(例如,如果你担心用户会要求你的计算器计算9**(9**9)
),你需要运行它另一个过程。这是充分隔离它的唯一简单方法。在事件系统或甚至不同的线程中运行它是不够的。也可以将其分解成与其他解决方案类似的小块,但需要非常小心的处理,通常是不值得的;无论如何,这不允许你做与运行Python代码完全相同的事情。
答案 2 :(得分:4)
我在eventlet库中找到了这个:
http://eventlet.net/doc/modules/timeout.html
from eventlet.timeout import Timeout
timeout = Timeout(seconds, exception)
try:
... # execution here is limited by timeout
finally:
timeout.cancel()
答案 3 :(得分:3)
如果与网络相关,您可以尝试:
import socket
socket.setdefaulttimeout(number)
答案 4 :(得分:2)
对于“普通”Python代码,在C扩展或I / O等待中不会延长时间,您可以通过设置跟踪函数sys.settrace()
来实现目标,该函数在超时时中止正在运行的代码到了。
这是否足够取决于您运行的代码的合作或恶意程度。如果它表现良好,则跟踪功能就足够了。
答案 5 :(得分:2)
另一种方法是使用faulthandler:
import time
import faulthandler
faulthandler.enable()
try:
faulthandler.dump_tracebacks_later(3)
time.sleep(10)
finally:
faulthandler.cancel_dump_tracebacks_later()
N.B:faulthandler模块是python3.3中stdlib的一部分。
答案 6 :(得分:0)
如果您正在运行预期在设定时间后死亡的代码,那么您应该正确编写它,以便对关闭没有任何负面影响,无论是线程还是子进程。带撤消的命令模式在这里很有用。
所以,它实际上取决于你杀死它时线程正在做什么。如果它只是处理数字谁关心你是否杀了它。如果它与文件系统进行交互并且你杀了它,那么也许你应该重新考虑你的策略。
在线程方面,Python支持什么?守护程序线程和连接。为什么如果你在守护进程仍处于活动状态时加入一个守护进程,python会让主线程退出?因为它理解有人使用守护程序线程(希望)以一种在该线程死亡时无关紧要的方式编写代码。在这种情况下,为连接提供超时,然后让主要死亡,从而使用任何守护程序线程,是完全可以接受的。
答案 7 :(得分:0)
我以这种方式解决了这个问题: 对我来说工作得很好(在Windows中并且根本不重)我希望它对某人有用)
import threading
import time
class LongFunctionInside(object):
lock_state = threading.Lock()
working = False
def long_function(self, timeout):
self.working = True
timeout_work = threading.Thread(name="thread_name", target=self.work_time, args=(timeout,))
timeout_work.setDaemon(True)
timeout_work.start()
while True: # endless/long work
time.sleep(0.1) # in this rate the CPU is almost not used
if not self.working: # if state is working == true still working
break
self.set_state(True)
def work_time(self, sleep_time): # thread function that just sleeping specified time,
# in wake up it asking if function still working if it does set the secured variable work to false
time.sleep(sleep_time)
if self.working:
self.set_state(False)
def set_state(self, state): # secured state change
while True:
self.lock_state.acquire()
try:
self.working = state
break
finally:
self.lock_state.release()
lw = LongFunctionInside()
lw.long_function(10)
主要的想法是创建一个线程,它将与“长时间工作”平行休眠。并且在唤醒(超时后)更改安全变量状态时,长函数在其工作期间检查安全变量。 我是Python编程的新手,所以如果该解决方案有基本错误,如资源,时间,死锁问题,请回复))。
答案 8 :(得分:0)
使用'解决问题。构建和合并来自
的解决方案这个线程更好用。
import threading, time
class Exception_TIMEOUT(Exception):
pass
class linwintimeout:
def __init__(self, f, seconds=1.0, error_message='Timeout'):
self.seconds = seconds
self.thread = threading.Thread(target=f)
self.thread.daemon = True
self.error_message = error_message
def handle_timeout(self):
raise Exception_TIMEOUT(self.error_message)
def __enter__(self):
try:
self.thread.start()
self.thread.join(self.seconds)
except Exception, te:
raise te
def __exit__(self, type, value, traceback):
if self.thread.is_alive():
return self.handle_timeout()
def function():
while True:
print "keep printing ...", time.sleep(1)
try:
with linwintimeout(function, seconds=5.0, error_message='exceeded timeout of %s seconds' % 5.0):
pass
except Exception_TIMEOUT, e:
print " attention !! execeeded timeout, giving up ... %s " % e