我正试图用多处理库在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解决方案,从而得到了这个答案。
谢谢大家!