限制Python中的函数执行

时间:2015-02-13 19:34:06

标签: python multithreading

有很多类似的问题和答案,但我仍然无法找到可靠的答案。

所以,我有一个功能,可能会运行太长时间。函数是私有的,在某种意义上我无法更改代码。

我想将执行时间限制为60秒。 我尝试了以下方法:

  1. Python信号。不要在Windows和多线程envorinment(mod_wsgi)上工作。
  2. 主题。很好的方式,但线程无法停止,所以它甚至在提升TimeoutException之后仍然存在。
  3. multiprocessing python模块。我有酸洗问题,我不知道如何解决它们。我想制作time_limit装饰器,并且在顶级导入所需的功能时出现问题。长时间执行的函数是实例方法,包装它也没有帮助......
  4. 那么,上述问题是否有很好的解决方案? 如何杀死线程,我开始了吗? 如何使用子过程并避免酸洗问题? subprocess模块是否有任何帮助?

    谢谢。

2 个答案:

答案 0 :(得分:2)

我认为多处理方法是您唯一真正的选择。你纠正了线程不能被杀死(很好)并且信号有跨平台问题。这是一个多处理实现:

import multiprocessing
import Queue

def timed_function(return_queue):
    do_other_stuff()
    return_queue.put(True)
    return

def main():

    return_queue = multiprocessing.Manager().Queue()

    proc = multiprocessing.Process(target=timed_function, args=(return_queue,))
    proc.start()

    try:

        # wait for 60 seconds for the function to return a value
        return_queue.get(timeout=60)

    except Queue.Empty:
        # timeout expired
        proc.terminate() # kill the subprocess
        # other cleanup

我知道你说你有酸洗问题,但几乎总能通过重构来解决。例如,您说您的long函数是一个实例方法。 可以包装这些类型的函数,以便在多处理中使用它们:

class TestClass(object):
    def timed_method(self, return_queue):
        do_other_stuff()
        return_queue.put(True)
        return

要在工作池中使用该方法,请将此包装器添加到模块的顶层:

def _timed_method_wrapper(TestClass_object, return_queue):
    return TestClass_object(return_queue)

现在,您可以从同一类的不同方法对此类方法使用apply_async

def run_timed_method():
    return_queue = multiprocessing.Manager().Queue()
    pool = multiprocessing.Pool()
    result = pool.apply_async(_timed_method_wrapper, args=(self, return_queue))

我非常确定只有在您使用multiprocessing.Pool而不是使用multiprocessing.Process对象启动子进程时才需要这些包装器。此外,我敢打赌,很多人会对这个结构感到不满,因为你正在打破类所提供的漂亮,干净的抽象,并且还会在类和其他随机包装函数之间创建依赖关系。你必须要决定是否让你的代码更难看是值得的。

答案 1 :(得分:-2)

answerIs it possible to kill a process on Windows from within Python?可能有所帮助: 你需要杀死那个子进程或线程: "Terminating a subprocess on windows"

也许TerminateThread帮助