使用多处理在Python中创建超时函数



我正试图用多处理库在Python 2.7.11(在Windows上)中创建一个超时函数。

我的基本目标是,如果函数超时,返回一个值,如果没有超时,返回实际值。

我的方法如下:

from multiprocessing import Process, Manager
def timeoutFunction(puzzleFileName, timeLimit):
  manager = Manager()
  returnVal = manager.list()
  # Create worker function
  def solveProblem(return_val):
    return_val[:] = doSomeWork(puzzleFileName) # doSomeWork() returns list
  p = Process(target=solveProblem, args=[returnVal])
  p.start()
  p.join(timeLimit)
  if p.is_alive():
    p.terminate()
    returnVal = ['Timeout']
  return returnVal

我这样调用函数:

if __name__ == '__main__':
  print timeoutFunction('example.txt', 600)

不幸的是,这不起作用,我在pickle.py 中收到了某种EOF错误

有人看到我做错了什么吗?

提前感谢,
Alexander

编辑:doSomeWork()不是一个实际的函数。只是我做的其他一些工作的填充。这些工作不是并行完成的,也不使用任何共享变量。我只想运行一个函数,并且可能会超时。

您可以使用Pebble库来实现这一点。

from pebble import concurrent
from concurrent.futures import TimeoutError
TIMEOUT_IN_SECONDS = 10
@concurrent.process(timeout=TIMEOUT_IN_SECONDS)
def function(foo, bar=0):
    return foo + bar
future = function(1, bar=2)
try:
    result = future.result()  # blocks until results are ready or timeout
except TimeoutError as error:
    print "Function took longer than %d seconds" % error.args[1]
    result = 'timeout'

文档中有更完整的示例。

如果函数超时,库将终止该函数,因此您不必担心IO或CPU被浪费。

编辑:

如果你正在做一项任务,你仍然可以看看它的实现。

简称:

from multiprocessing import Pipe, Process
def worker(pipe, function, args, kwargs):
    try:
        results = function(*args, **kwargs)
    except Exception as error:
        results = error
    pipe.send(results)
pipe = Pipe(duplex=False)
process = Process(target=worker, args=(pipe, function, args, kwargs))
if pipe.poll(timeout=5):
    process.terminate()
    process.join()
    results = 'timeout'
else:
    results = pipe.recv()

Pebble提供了一个整洁的API,处理了拐角情况,并使用了更健壮的机制。然而,这或多或少就是它在幕后所做的。

问题似乎是函数solveProblem是在我的外部函数中定义的。Python似乎不喜欢这样。我一把它移到外面,效果就很好。

我将把noxdafox答案标记为一个答案,因为我实现了pebble解决方案,从而得到了这个答案。

谢谢大家!

最新更新