Python 使用future处理并发问题方案详解
在Python中,处理并发问题有多种方法,其中较为常用的是使用future
模块。本文将对future
模块的使用进行详细讲解,包括其基本用法、示例说明等。
什么是future
future
是Python标准库中的一个模块,用于在多线程/多进程编程中处理异步计算任务。它提供了一些类,如Future
、ThreadPoolExecutor
、ProcessPoolExecutor
等,方便用户进行异步计算任务和并发编程。
Future
是future
模块的核心类。它通过异步方式执行和管理计算任务,并在任务完成后返回结果。ThreadPoolExecutor
和ProcessPoolExecutor
都是通过多线程/多进程方式创建一个池子,方便管理异步任务。
future模块基本用法
Future类
Future
类表示一个异步计算任务,它的主要作用是通过异步管理任务,并在任务完成后返回结果。
from concurrent.futures import Future
# 创建一个Future对象
future = Future()
Future
类提供了以下方法来管理异步任务:
add_done_callback(fn)
:添加任务完成时的回调方法fn
done()
:判断任务是否完成,如果完成返回True
,否则返回False
result(timeout=None)
:获取任务的结果,如果任务未完成会一直等待,如果在指定的timeout
时间内没有获得结果,则触发TimeoutError
异常。exception(timeout=None)
:获取任务的异常,如果任务未出现异常则返回None
ThreadPoolExecutor类和ProcessPoolExecutor类
ThreadPoolExecutor
类和 ProcessPoolExecutor
类都是通过多线程/多进程方式创建一个池子,以方便管理异步任务。
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
# 创建一个线程池
with ThreadPoolExecutor() as executor:
# 添加异步任务
future = executor.submit(func, *args, **kwargs)
# 创建一个进程池
with ProcessPoolExecutor() as executor:
# 添加异步任务
future = executor.submit(func, *args, **kwargs)
ThreadPoolExecutor
和 ProcessPoolExecutor
都支持以下方法:
submit(fn, *args, **kwargs)
:用于将fn(*args, **kwargs)
提交到池子中,并返回一个Future
对象,表示异步任务。shutdown(wait=True)
:用于关闭池子,默认参数为True
,表示在所有异步任务完成后关闭池子,否则立即关闭。
示例说明
使用ThreadPoolExecutor处理并发问题
通过以下示例,演示如何使用ThreadPoolExecutor
类处理并发问题。在示例中,我们需要从几个网站上下载图片并保存到本地文件中。本例使用threading
模块进行下载。
import urllib.request
import threading
import os
from concurrent.futures import ThreadPoolExecutor
def download(url, filename):
urllib.request.urlretrieve(url, filename)
def main():
urls = [
'https://www.example.com/image1.jpg',
'https://www.example.com/image2.jpg',
'https://www.example.com/image3.jpg'
]
with ThreadPoolExecutor() as executor:
for url in urls:
# 将下载任务提交到线程池中
executor.submit(download, url, os.path.basename(url))
if __name__ == '__main__':
main()
在示例中,我们首先定义了一个download()
函数,用于从指定的URL下载图片并保存到本地文件中。接下来,我们使用ThreadPoolExecutor
类创建了一个线程池,并将下载任务提交到线程池中。
使用ProcessPoolExecutor处理并发问题
通过以下示例,演示如何使用ProcessPoolExecutor类处理并发问题。在示例中,我们需要对一些URL进行Ping测试,并输出Ping的结果。本例使用multiprocessing模块进行Ping测试。
import subprocess
from concurrent.futures import ProcessPoolExecutor
def ping(url):
# 注意:Windows下的ping参数与*nix不同
cmd = ['-n', '3', '-w', '1000', url] if os.name == 'nt' else ['ping', '-c', '3', '-W', '1', url]
result = subprocess.run(cmd, stderr=subprocess.PIPE)
if result.returncode == 0:
print(f'{url}: Ping Ok')
else:
print(f'{url}: Ping Failed')
def main():
urls = [
'www.baidu.com',
'www.google.com',
'www.example.com'
]
with ProcessPoolExecutor() as executor:
for url in urls:
# 将Ping任务提交到进程池中
executor.submit(ping, url)
if __name__ == '__main__':
main()
在示例中,我们首先定义了一个ping()
函数,用于对指定的URL进行Ping测试。接下来,我们使用ProcessPoolExecutor
类创建了一个进程池,并将Ping任务提交到进程池中。