Python并发编程之未来模块Futures
在Python 3中,concurrent.futures是处理异步任务和多线程任务的标准库。这个库包含两个类:ThreadPoolExecutor和ProcessPoolExecutor,它们使得编写并行代码变得容易。concurrent.futures模块提供了Future类来表示异步操作结果的一个简单方式。
Futures的基本概念
Future是异步编程的编程模型之一。简单地讲,Future是一个代理,用于访问尚未完成的操作的结果。Future对象可以被提交到ThreadPoolExecutor线程池中,每个Future对象表示一个尚未完成的操作,它会在未来的某个时间点被提交到线程池中执行。
因此,Future对于异步编程非常关键。使用Future,您可以避免阻塞您的主线程。当一个线程处于"等待结果"状态时,它会被挂起并释放CPU资源,以便其他线程可以使用它们。这样可以确保您的程序始终保持高效。
Future的用途
Future对于Python并发编程是非常有用的。它们可以用于异步I/O操作(如网络I/O、文件I/O、消息I/O等),也可以用于CPU密集型操作(如图像处理、数据分析等)。
当执行Futures时,它们会立即返回,不会阻塞主线程,因此主线程可以继续执行其他操作,当您需要结果时,您可以使用Future对象的result()方法获取它们(此时可能需要等待)。
示例1:使用ThreadPoolExecutor执行异步任务
首先,让我们看一个使用ThreadPoolExecutor的例子。我们使用ThreadPoolExecutor和Future对象创建一个异步任务来计算从1到1000的所有数字的总和,然后在计算完成后获取它的结果。
import concurrent.futures
def calculate_sum(num_list):
return sum(num_list)
if __name__ == '__main__':
num_list = list(range(1,1001))
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(calculate_sum, num_list)
print(future.result())
代码解析:
- 首先,我们导入了concurrent.futures模块,并定义了一个名为“ calculate_sum”的函数,它将执行数字列表的总和
- 我们创建了数字列表
num_list
并将其传递给Future对象,我们将使用ThreadPoolExecutor
来处理Future对象。 - 我们使用执行器executor的submit()方法将异步任务提交给ThreadPoolExecutor。submit方法返回一个Future对象,它代表的是已经提交的异步任务的结果(在本例中是数字列表的总和)。
- 最后,我们使用Future对象的result()方法获取异步任务的结果并打印它。
上面的代码非常简单,但这里有一些需要注意的事项:
- 当提交任务给Executor时,任务并没有立即执行,Executor内部会安排这些任务的执行。
- 使用with
语句,可以在使用完后自动关闭线程池,释放资源。
示例2:使用ProcessPoolExecutor执行CPU密集型任务
现在我们来学习如何使用ProcessPoolExecutor,执行一个CPU密集型任务,并计算我们计算 Pi值的时间。因为这是一个CPU密集型任务,所以将使用ProcessPoolExecutor代替ThreadPoolExecutor。
import concurrent.futures
import time
import math
def calculate_pi(digits):
pi = math.pi
return format(pi, '.' + str(digits) + 'f')
if __name__ == '__main__':
start = time.time()
with concurrent.futures.ProcessPoolExecutor() as executor:
future = executor.submit(calculate_pi, 100000)
print(future.result())
end = time.time()
print('Time taken: {}s'.format(round(end-start, 2)))
代码解析:
1. 我们导入concurrent.futures模块和time,math模块。calculate_pi
函数计算pi值并将其格式化为一个字符串。
2. 我们使用ProcessPoolExecutor代替ThreadPoolExecutor来处理CPU密集型任务。
3. 在开始计时之前,我们使用ProcessPoolExecutor的submit()方法将异步任务提交给ProcessPoolExecutor。
4. 我们使用Future对象的result()方法获取Pi计算的结果,并计算用于计算pi值的时间。
在本例中,我们使用Future对象执行了一个非常耗时的任务(计算100000位Pi值),但由于使用了ProcessPoolExecutor,我们的代码始终保持了高效。
结论
在Python3中,通过concurrent.futures模块内置的ThreadPoolExecutor和ProcessPoolExecutor线程池,通过submit()方法提交异步任务,并使用Future对象来获取任务的返回结果,能够让开发者更方便、更高效地进行并发编程的开发。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python并发编程之未来模块Futures - Python技术站