Python 中的多线程和多处理
阅读:17
点赞:0
一. 引言
在这篇博客中,我们将探讨多线程和多进程在 Python 中的应用。在当今多核处理器的世界里,利用并发编程技术至关重要,以优化性能。Python 提供了两个强大的模块用于并行执行:threading
用于多线程,而 multiprocessing
用于多进程。
二. Python 中的多线程
多线程允许多个线程在单个进程中并发运行。对于 I/O 密集型任务(如网络请求、文件操作等)来说,多线程尤其有效,因为这些任务往往需要等待外部操作完成。下面我们将通过一个示例,展示如何使用多线程进行网页抓取。
示例
我们将创建一个简单的网页抓取程序,并同时从多个 URL 下载内容。在运行以下示例之前,请确保使用 pip install requests
安装 requests
包。
import threading # 导入 threading 模块
import requests # 导入 requests 模块
import time # 导入 time 模块
# 定义下载内容的函数
def download_content(url):
response = requests.get(url) # 发送 GET 请求获取网页内容
print(f"Downloaded {len(response.content)} bytes from {url}") # 输出下载的字节数
# 定义要抓取的 URL 列表
urls = [
"https://www.python.org", # Python 官方网站
"https://www.github.com", # GitHub 官方网站
]
start_time = time.time() # 记录开始时间
threads = [] # 存储线程的列表
for url in urls: # 遍历每个 URL
thread = threading.Thread(target=download_content, args=(url,)) # 创建线程
threads.append(thread) # 将线程添加到列表中
thread.start() # 启动线程
for thread in threads: # 等待所有线程完成
thread.join() # 等待线程结束
end_time = time.time() # 记录结束时间
print(f"Total execution time: {end_time - start_time:.2f} seconds") # 输出总执行时间
在上面的 Python 代码中,为每个 URL 创建了一个独立的线程,允许同时下载内容。join()
方法确保所有线程在程序退出之前完成。
三. Python 中的多进程
虽然多线程受限于 CPython 的全局解释器锁(GIL),多进程可以通过生成独立的 Python 进程来充分利用多个 CPU 核心。接下来,我们将通过一个示例来计算质数。
示例
我们将使用多个进程来计算质数。
import multiprocessing # 导入 multiprocessing 模块
import time # 导入 time 模块
# 定义检查质数的函数
def is_prime(n):
if n < 2: # 如果小于 2,返回 False
return False
for i in range(2, int(n ** 0.5) + 1): # 检查从 2 到 n 的平方根之间的数
if n % i == 0: # 如果能整除,返回 False
return False
return True # 返回 True,表示是质数
# 定义查找质数的函数
def find_primes(start, end):
return [num for num in range(start, end) if is_prime(num)] # 返回指定范围内的所有质数
if __name__ == "__main__": # 确保主程序运行
start_time = time.time() # 记录开始时间
pool = multiprocessing.Pool(processes=4) # 创建进程池,指定进程数量
ranges = [(1, 25000), (25001, 50000), (50001, 75000), (75001, 100000)] # 定义范围
results = pool.starmap(find_primes, ranges) # 使用 starmap 并行执行查找质数的函数
all_primes = [prime for sublist in results for prime in sublist] # 将所有子列表合并为一个列表
end_time = time.time() # 记录结束时间
print(f"Found {len(all_primes)} prime numbers") # 输出找到的质数数量
print(f"Total execution time: {end_time - start_time:.2f} seconds") # 输出总执行时间
在上面的 Python 代码中,使用一个进程池来将质数计算任务分配到多个 CPU 核心上。
四. 选择多线程还是多进程
-
对于 I/O 密集型任务(如网络操作、文件 I/O),使用多线程。 -
对于需要并行计算的 CPU 密集型任务,使用多进程。 -
多线程占用系统资源较少,但受限于 GIL。 -
多进程开销更大,但可以充分利用多个 CPU 核心。
五. 总结
多线程和多进程都是提升 Python 应用性能的强大工具。通过理解它们的优势和适用场景,您可以为具体需求选择合适的方法,以提升程序的执行效率。