返回先返回的表达式

时间:2013-02-08 00:38:07

标签: python multithreading concurrency

我有两个不同的函数fg,它们使用不同的算法计算相同的结果。有时一个或另一个需要时间,而另一个则快速终止。我想创建一个同时运行每个函数的新函数,然后从完成的第一个函数返回结果。

我想用更高阶函数创建该函数

h = firstresult(f, g)

在Python中实现这一目标的最佳方法是什么?

我怀疑解决方案涉及线程化。我想避免讨论GIL。

4 个答案:

答案 0 :(得分:2)

我只想使用Queue。启动线程,第一个有结果的线程写入队列。

代码

from threading import Thread
from time import sleep
from Queue import Queue

def firstresult(*functions):
    queue = Queue()
    threads = [] 
    for f in functions:
        def thread_main():
            queue.put(f())
        thread = Thread(target=thread_main)
        threads.append(thread)
        thread.start()
    result = queue.get()
    return result

def slow():
    sleep(1)
    return 42 

def fast():
    return 0

if __name__ == '__main__':
    print firstresult(slow, fast)

现场演示

http://ideone.com/jzzZX2

备注

停止线程是一个完全不同的主题。为此,您需要向需要定期检查的线程添加一些state变量。由于我想保持这个例子简短,我只是假设那部分,并假设所有工人都有时间完成他们的工作,即使结果从未被读过。

根据提问者的要求,跳过关于Gil的讨论。 ; - )

答案 1 :(得分:1)

在新的工作线程中运行每个函数,2个工作线程将结果发送回1个项目队列中的主线程或类似的东西。当主线程收到胜利者的结果时,它会杀死(做python线程支持kill还是大声笑。)两个工作线程以避免浪费时间(一个函数可能需要几个小时,而另一个函数只需要一秒钟)。

如果需要,用过程替换单词thread。

答案 2 :(得分:1)

您需要在另一个进程(使用多处理)或另一个线程中运行每个函数。 如果两者都是CPU绑定的,多线程获得了很多帮助 - 完全由于GIL - 所以多处理就是这样。

如果返回值是一个pickleable(可序列化)对象,我创建的这个装饰器只是在后台运行该函数,在另一个过程中:

https://bitbucket.org/jsbueno/lelo/src

这不是你想要的 - 因为它们都是非阻塞的并且立即开始执行。这个装饰器的tirck就是当你试图使用返回值时阻塞(并等待函数完成)。

但另一方面 - 它只是一个完成所有工作的装饰师。

答案 3 :(得分:1)

现在 - 与我对另一个答案的建议不同,这段代码完全符合您的要求:

from multiprocessing import Process, Queue

import random
import time


def firstresult(func1, func2):
    queue = Queue()
    proc1 = Process(target=func1,args=(queue,))
    proc2 = Process(target=func2, args=(queue,))
    proc1.start();proc2.start()
    result = queue.get()
    proc1.terminate(); proc2.terminate()
    return result

def algo1(queue):
    time.sleep(random.uniform(0,1))
    queue.put("algo 1")

def algo2(queue):
    time.sleep(random.uniform(0,1))
    queue.put("algo 2")

print firstresult(algo1, algo2)