Python中非常简单的并发编程

Ror*_*ory 9 python concurrency

我有一个简单的Python脚本,它使用两个更复杂的Python脚本,并对结果做了一些事情.

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

import Foo
import Bar

output = []

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

output.append(a)
output.append(b)
Run Code Online (Sandbox Code Playgroud)

这两种方法都需要很长时间才能运行,并且都不依赖于另一种方法,所以显而易见的解决方案是并行运行它们.我如何实现这一目标,但要确保维护订单:无论哪一个完成,必须等待另一个完成,然后脚本才能继续.

让我知道如果我没有说清楚,我已尽力使示例代码尽可能简单.

编辑:

谢谢Amber,您的解决方案只需稍作修改即可.

而不是在每个线程创建时调用start(),我将它们设置为:

import Foo
import Bar

output = []

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

output.append(a)
output.append(b)
Run Code Online (Sandbox Code Playgroud)

没有这个,我得到了错误__CODE__和一些非常奇怪的并发行为.如果您在下面编辑答案,我会将其标记为已解决.

Amb*_*ber 22

一般来说,你习惯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()
Run Code Online (Sandbox Code Playgroud)

然后要求它们都已完成,请同时使用.join():

a_thread.join()
b_thread.join()
Run Code Online (Sandbox Code Playgroud)

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

output = [results['a'], results['b']]
Run Code Online (Sandbox Code Playgroud)

注意:如果两个任务本身都是CPU密集型的,那么您可能需要考虑multiprocessing- 由于Python的GIL,给定的Python进程将只使用一个CPU核心,而multiprocessing可以将任务分配到单独的核心.但是,它的开销略高threading,因此如果任务的CPU占用率较低,则可能效率不高.

  • 线程有助于空闲代码.如果它有很多繁重的计算,你应该建议多处理,因为线程只会在这种情况下增加滞后. (3认同)

faz*_*kan 8

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
Run Code Online (Sandbox Code Playgroud)

这是您的程序的过程版本.

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

现在由于在一个过程中没有共享的数据结构,因此不用担心LOCKS,因为无论GIL如何都可以工作,所以你真正享受多处理器的真正威力.

要记住的简单注意事项:进程与不使用共享数据结构的线程相同(一切都是孤立的,并且专注于消息传递.)

看看dabeaz.com他曾经对并发编程做了很好的演讲.