使用多处理在 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 解决方案让我得到了这个答案。

谢谢大家!