10

我有一个简单的 Python 脚本,它使用两个更复杂的 Python 脚本,并对结果进行处理。

我有两个模块,Foo 和 Bar,我的代码如下:

import Foo
import Bar

output = []

a = Foo.get_something()
b = Bar.get_something_else()

output.append(a)
output.append(b)

这两种方法都需要很长时间才能运行,而且都不依赖于另一个,因此显而易见的解决方案是并行运行它们。我怎样才能做到这一点,但要确保保持顺序:无论哪个先完成,都必须等待另一个完成,然后脚本才能继续

如果我还不够清楚,请告诉我,我已尝试使示例代码尽可能简单。

4

2 回答 2

23

通常,您会使用它threading来执行此操作。

首先,为您要并行运行的每件事创建一个线程:

import threading

import Foo
import Bar

results = {}

def get_a():
    results['a'] = Foo.get_something()
a_thread = threading.Thread(target=get_a)
a_thread.start()

def get_b():
    results['b'] = Bar.get_something_else()
b_thread = threading.Thread(target=get_b)
b_thread.start()

然后要求他们两个都完成,.join()在两者上使用:

a_thread.join()
b_thread.join()

此时您的结果将在results['a']and中results['b'],因此如果您想要一个有序列表:

output = [results['a'], results['b']]

注意:如果这两个任务本质上都是 CPU 密集型的,您可能需要考虑multiprocessing改为 - 由于 Python 的 GIL,给定的 Python 进程将只使用一个 CPU 内核,而multiprocessing可以将任务分配到不同的内核。但是,它的开销比 略高threading,因此如果任务的 CPU 密集度较低,则可能效率不高。

于 2012-05-07T00:30:25.377 回答
10
import multiprocessing

import Foo
import Bar

results = {}

def get_a():
    results['a'] = Foo.get_something()



def get_b():
    results['b'] = Bar.get_something_else()

process_a = multiprocessing.Process(target=get_a)
process_b = multiprocessing.Process(target=get_b)


process_b.start()
process_a.start()


process_a.join
process_b.join

这是您的程序的进程版本。

注意:在线程中存在共享数据结构,因此您必须担心锁定以避免错误操作数据加上上面提到的琥珀色,它还存在 GIL(全局解释器锁定)问题,并且由于您的两个任务都是 CPU 密集型的,因此这意味着由于调用通知线程获取和释放线程,这将花费更多时间。但是,如果您的任务是 I/O 密集型的,那么它不会产生太大影响。

现在,由于进程中没有共享数据结构,因此无需担心 LOCKS,并且由于它与 GIL 无关,因此您实际上可以享受多处理器的真正威力。

要记住的简单说明:进程与线程相同,只是不使用共享数据结构(一切都是独立工作的,并且专注于消息传递。)

查看dabeaz.com,他曾经对并发编程做了一个很好的介绍。

于 2014-11-21T19:08:16.813 回答