在Windows中在一定时间后终止一个函数
我看了很多关于使用线程、子进程等的帖子。感觉这些内容对我想做的事情来说太复杂了……
我只想在经过一段时间后停止执行一个函数。
def big_loop(bob):
x = bob
start = time.time()
while True:
print time.time()-start
这个函数是一个无尽的循环,根本不会抛出任何错误或异常。我不太明白“命令、shell、子进程、线程”等等和这个函数有什么区别,这也是我在处理子进程时遇到麻烦的原因。
我在这里找到了一段代码,试过了,但你可以看到它在10秒后还在继续打印:
import time
import threading
import subprocess as sub
import time
class RunCmd(threading.Thread):
def __init__(self, cmd, timeout):
threading.Thread.__init__(self)
self.cmd = cmd
self.timeout = timeout
def run(self):
self.p = sub.Popen(self.cmd)
self.p.wait()
def Run(self):
self.start()
self.join(self.timeout)
if self.is_alive():
self.p.terminate()
self.join()
def big_loop(bob):
x = bob
start = time.time()
while True:
print time.time()-start
RunCmd(big_loop('jimijojo'), 10).Run() #supposed to quit after 10 seconds, but doesn't
x = raw_input('DONEEEEEEEEEEEE')
有没有简单的方法可以结束这个函数?正如你在我上面的尝试中看到的,它在20秒后并没有终止,还是继续运行……
***哦,对了,我也看过关于使用信号的内容,但我在Windows上,所以不能使用闹钟功能……(python 2.7)
**假设这个“无限运行的函数”不能被修改或改变成非无限的,如果我能改变这个函数,那我就直接把它改成非无限的了,不是吗?
这里有一些类似的问题,但我还没能把他们的代码移植到我的简单函数上:也许你可以?
Windows中的signal.alarm替代方案 [Python]
好的,我试了一个我收到的答案,它有效……但如果我去掉if __name__ == "__main__":
这行代码,我该怎么用?当我去掉这行代码时,循环就像之前一样永远不会结束……
import multiprocessing
import Queue
import time
def infinite_loop_function(bob):
var = bob
start = time.time()
while True:
time.sleep(1)
print time.time()-start
print 'this statement will never print'
def wrapper(queue, bob):
result = infinite_loop_function(bob)
queue.put(result)
queue.close()
#if __name__ == "__main__":
queue = multiprocessing.Queue(1) # Maximum size is 1
proc = multiprocessing.Process(target=wrapper, args=(queue, 'var'))
proc.start()
# Wait for TIMEOUT seconds
try:
timeout = 10
result = queue.get(True, timeout)
except Queue.Empty:
# Deal with lack of data somehow
result = None
finally:
proc.terminate()
print 'running other code, now that that infinite loop has been defeated!'
print 'bla bla bla'
x = raw_input('done')
4 个回答
1
没有简单的方法可以在一段时间后强制结束一个函数,除非把这个函数放在一个单独的进程中。更好的办法可能是重新写这个函数,让它在指定的时间后自动返回:
import time
def big_loop(bob, timeout):
x = bob
start = time.time()
end = start + timeout
while time.time() < end:
print time.time() - start
# Do more stuff here as needed
1
你难道不能直接从循环中返回吗?
start = time.time()
endt = start + 30
while True:
now = time.time()
if now > endt:
return
else:
print end - start
6
使用 multiprocessing
模块中的基本组件:
import multiprocessing
import Queue
TIMEOUT = 5
def big_loop(bob):
import time
time.sleep(4)
return bob*2
def wrapper(queue, bob):
result = big_loop(bob)
queue.put(result)
queue.close()
def run_loop_with_timeout():
bob = 21 # Whatever sensible value you need
queue = multiprocessing.Queue(1) # Maximum size is 1
proc = multiprocessing.Process(target=wrapper, args=(queue, bob))
proc.start()
# Wait for TIMEOUT seconds
try:
result = queue.get(True, TIMEOUT)
except Queue.Empty:
# Deal with lack of data somehow
result = None
finally:
proc.terminate()
# Process data here, not in try block above, otherwise your process keeps running
print result
if __name__ == "__main__":
run_loop_with_timeout()
你也可以用 Pipe
和 Connection
这对组合来实现这个功能,不过我对它们的使用方法不太了解。你可以调整睡眠时间或者 TIMEOUT
来观察这两种情况的表现。