如何同时运行两个python循环?

如何同时运行两个python循环?,python,concurrency,Python,Concurrency,假设在Python中有以下内容 # A loop for i in range(10000): Do Task A # B loop for i in range(10000): Do Task B 如何在Python中同时运行这些循环?为什么要同时运行这两个进程?是因为你认为他们会走得更快(他们很有可能不会)。为什么不在同一个循环中运行任务,例如 for i in range(10000): doTaskA() doTaskB() 对于您的问题,最明显的答

假设在Python中有以下内容

# A loop
for i in range(10000):
    Do Task A

# B loop
for i in range(10000):
    Do Task B

如何在Python中同时运行这些循环?

为什么要同时运行这两个进程?是因为你认为他们会走得更快(他们很有可能不会)。为什么不在同一个循环中运行任务,例如

for i in range(10000):
    doTaskA()
    doTaskB()
对于您的问题,最明显的答案是使用线程——请参阅python模块。然而,线程是一个大的主题,有很多陷阱,所以在你走这条路之前,请仔细阅读

或者,您可以使用python模块在单独的进程中运行这些任务。如果这两项任务都是CPU密集型的,这将更好地利用计算机上的多核


还有其他选项,如协程、stackless tasklets、greenlets、CSP等,但如果不了解更多关于任务A和任务B的信息以及它们为什么需要同时运行,就不可能给出更具体的答案。

如何:范围(10000)内的i循环:执行任务A,执行任务B?如果没有更多信息,我没有更好的答案。

您可以使用或。

如果您想要并发,下面是一个非常简单的示例:

from multiprocessing import Process

def loop_a():
    while 1:
        print("a")

def loop_b():
    while 1:
        print("b")

if __name__ == '__main__':
    Process(target=loop_a).start()
    Process(target=loop_b).start()
from multiprocessing import Process


p1 = Process(target=taskA, args=(*args, **kwargs))
p2 = Process(target=taskB, args=(*args, **kwargs))

p1.start()
p2.start()
这只是我能想到的最基本的例子。一定要阅读以了解发生了什么

如果您想将数据发送回程序,我建议使用队列(根据我的经验,这是最容易使用的)


如果你不介意的话,你可以用一根线来代替。流程实例化的成本更高,但它们提供真正的并发性。

对于您想要的内容,有许多可能的选项:

使用循环 正如许多人指出的那样,这是最简单的方法

for i in xrange(10000):
    # use xrange instead of range
    taskA()
    taskB()
优点:易于理解和使用,不需要额外的库

缺点:taskB必须在taskA之后完成,否则。它们不可能同时运行

多进程 另一个想法是:同时运行两个进程,python提供,下面是一个简单的示例:

from multiprocessing import Process

def loop_a():
    while 1:
        print("a")

def loop_b():
    while 1:
        print("b")

if __name__ == '__main__':
    Process(target=loop_a).start()
    Process(target=loop_b).start()
from multiprocessing import Process


p1 = Process(target=taskA, args=(*args, **kwargs))
p2 = Process(target=taskB, args=(*args, **kwargs))

p1.start()
p2.start()
优点:任务可以在后台同时运行,您可以控制任务(结束、停止等),任务可以交换数据,如果它们竞争相同的资源,可以同步等

缺点:太重!操作系统将经常在它们之间切换,即使数据是冗余的,它们也有自己的数据空间。如果你有很多任务(比如100个或更多),这不是你想要的

穿线 线程就像进程,只是轻量级的。退房它们的用法非常相似:

import threading 


p1 = threading.Thread(target=taskA, args=(*args, **kwargs))
p2 = threading.Thread(target=taskB, args=(*args, **kwargs))

p1.start()
p2.start()
协同程序 像
greenlet
gevent
这样的库提供了一种称为协程(coroutines)的东西,它应该比线程更快。没有提供的例子,请谷歌如何使用它们,如果你有兴趣

优点:更灵活、更轻

缺点:需要额外的库,学习曲线。

我发现在“多处理”中使用“池”子模块可以在Python脚本中同时执行多个进程

仔细查看示例中的“#异步启动多个评估可能会使用更多流程”。一旦您了解了这些行在做什么,下面我构建的示例将非常有意义

import numpy as np
from multiprocessing import Pool

def desired_function(option, processes, data, etc...):
    # your code will go here. option allows you to make choices within your script
    # to execute desired sections of code for each pool or subprocess.

    return result_array   # "for example"


result_array = np.zeros("some shape")  # This is normally populated by 1 loop, lets try 4.
processes = 4
pool = Pool(processes=processes)
args = (processes, data, etc...)    # Arguments to be passed into desired function.

multiple_results = []
for i in range(processes):          # Executes each pool w/ option (1-4 in this case).
    multiple_results.append(pool.apply_async(param_process, (i+1,)+args)) # Syncs each.

results = np.array(res.get() for res in multiple_results)  # Retrieves results after
                                                           # every pool is finished!

for i in range(processes):
    result_array = result_array + results[i]  # Combines all datasets!

代码将基本上为一组进程运行所需的函数。您必须仔细确保您的函数能够区分每个进程(因此我添加了变量“option”。)此外,它不必是最终填充的数组,但对于我的示例,我就是这样使用它的。希望这可以简化或帮助您更好地理解Python中多处理的功能

只是关于线程模块的一点警告。python有一种称为全局解释器锁(GIL)的东西。这将阻止python的某些(大)区域同时运行,即使在单独的线程中也是如此。多处理没有这个问题——尽管它也有它自己的一堆陷阱。如果速度是问题,使用某种不同的
map
,列表理解或生成器表达式是可行的。我比Odomontois落后四分钟。我看到了17张赞成票,在我的Raspberry Pi 3上运行时,它没有打印任何内容。这是为什么?@Mahi我猜,但你需要把它放进一个文件并运行它。当文件运行时(即“如果我正在作为程序执行”),运行
下的代码块if uuuu name_uuu==“\uuuu main\uuuuu”
。如果要将其粘贴到python shell中,只需去掉
If
语句:)我在每个print()函数的末尾追加time.time(),并将循环次数限制为9次。这是我在终端中看到的:('a',1509314761.857559)('a',1509314761.857664)('a',1509314761.85767)('a',1509314761.857675)('a',1509314761.85768)('a',1509314761.857685)('a',1509314761.85769)('a',1509314761.857695)('a',1509314761.857699)('b',1509314761.858138)('b',1509314761.858229)('('b',1509314761.858234)('b',1509314761.858239)('b',1509314761.858244)('b',1509314761.858249)('b',1509314761.858253)('b',1509314761.858258)所以这不是真正的并发仪式?一个接一个地运行。它们都是非常不同的设计方法,这取决于您的问题。线程允许您共享进程内内存和资源,而多处理则不允许。请您解释一下
threadA.join()
threadB.join()是什么
for?@alvas是一个允许等待异步工作的方法。因为我们需要两个线程的结果,所以可以在所有作业执行后调用它。我明白。join是一个允许等待异步工作的方法。我不明白的是,从上面的示例中,我看不到A在等待什么,也看不到join实际上有什么好处 .