在Windows中在一定时间后终止一个函数

6 投票
4 回答
10064 浏览
提问于 2025-04-16 18:01

我看了很多关于使用线程、子进程等的帖子。感觉这些内容对我想做的事情来说太复杂了……

我只想在经过一段时间后停止执行一个函数。

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)

**假设这个“无限运行的函数”不能被修改或改变成非无限的,如果我能改变这个函数,那我就直接把它改成非无限的了,不是吗?

这里有一些类似的问题,但我还没能把他们的代码移植到我的简单函数上:也许你可以?

Python:在超时情况下杀死或终止子进程

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()

你也可以用 PipeConnection 这对组合来实现这个功能,不过我对它们的使用方法不太了解。你可以调整睡眠时间或者 TIMEOUT 来观察这两种情况的表现。

撰写回答