Python中非常简单的并发编程

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)

这两种方法的运行时间很长,它们之间相互独立,因此显而易见的解决方案是并行运行它们。但如何实现并行,又保证顺序不变?无论哪个先完成,都必须等待另一个完成才能继续执行脚本

如果我的表述不够清晰,请告诉我,我已经尽可能简化了示例代码。

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']results ['b']中,所以如果你想要一个有序列表:

output = [results['a'], results['b']]
注意:如果两个任务本质上都是CPU密集型的,你可能需要考虑使用multiprocessing - 由于Python的GIL,一个给定的Python进程只会使用一个CPU核心,而multiprocessing可以将任务分配到不同的核心上。然而,它比threading稍微多一些开销,因此如果任务不是很CPU密集型,那么它可能不太高效。

3
如果代码有空闲时间,使用线程会很有帮助。但如果有大量的繁重计算,建议使用多进程,因为在这种情况下,使用线程只会增加延迟。 - akaRem
是的,它需要很高的CPU性能。不过我会先让它正常工作;我已经快速查看了一下,API是相同的。 - Ivy
我已经尝试了一段时间,但是我一直在不断地收到错误提示:AttributeError: 'NoneType' object has no attribute 'join'这每次都是指向 a_thread。而 b_thread 则按预期工作。 - Ivy
@Blazemore 我稍微修改了一下代码,有一个小问题。 - Amber
你知道我为什么无法访问结果字典吗?我得到了键错误。让函数写入任何全局变量也给我带来了问题;它们根本没有被写入。 - Ivy

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

这是您程序的进程版本。

注意:在线程中,存在共享数据结构,因此必须考虑加锁以避免数据被错误操作。正如Amber上面提到的那样,它还存在GIL(全局解释器锁)问题。由于您的两个任务都是CPU密集型的,这意味着由于调用通知线程获取和释放线程,所以会需要更多时间。但如果您的任务是I/O密集型,则不会对其产生太大影响。

现在,由于进程中不存在共享数据结构,因此无需担心锁定问题,并且由于它可以不受GIL的影响工作,因此实际上可以享受到多处理器的真正强大之处。

简单提示:进程与线程相同,只是没有使用共享数据结构(一切都以隔离形式运作并专注于消息传递)。

请查看dabeaz.com,他曾就并发编程做过很好的演示。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接