使用多处理在 Python 中创建超时函数
Creating a timeout function in Python with multiprocessing
我正在尝试使用多处理库在 Python 2.7.11(在 Windows 上)创建一个超时函数。
我的基本目标是 return 如果函数超时则为一个值,如果没有超时则为实际值。
我的方法如下:
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 错误
谁能看出我做错了什么?
提前致谢,
亚历山大
编辑: 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'
documentation有更完整的例子。
如果超时,库会终止函数,因此您无需担心 IO 或 CPU 被浪费。
编辑:
如果您正在做作业,您仍然可以查看 its 实现。
简短示例:
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 解决方案让我得到了这个答案。
谢谢大家!
我正在尝试使用多处理库在 Python 2.7.11(在 Windows 上)创建一个超时函数。
我的基本目标是 return 如果函数超时则为一个值,如果没有超时则为实际值。
我的方法如下:
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 错误谁能看出我做错了什么?
提前致谢,
亚历山大
编辑: 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'
documentation有更完整的例子。
如果超时,库会终止函数,因此您无需担心 IO 或 CPU 被浪费。
编辑:
如果您正在做作业,您仍然可以查看 its 实现。
简短示例:
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 解决方案让我得到了这个答案。
谢谢大家!