Python异步编程(协程)、线程、进程简介
仅供个人学习记录,来源豆包ai
一、Python 异步编程(基于async
/await
和asyncio
库)
1. 概念
异步编程是一种让程序在遇到 I/O 密集型操作(如网络请求、文件读取等)时,不阻塞当前执行流程,而是可以继续去执行其他不依赖该 I/O 结果的任务,待 I/O 操作完成后再回来处理后续相关事务的编程方式。在 Python 中,通过async def
定义异步函数,使用await
关键字来暂停异步函数等待可等待对象(如其他异步函数返回的协程对象或特定异步操作对应的对象)完成,而asyncio
库的事件循环则负责调度和执行这些异步任务。
2. 特点
await
关键字进行协作式的执行切换,不需要像线程那样依赖操作系统内核来进行调度和切换(线程切换涉及到内核态和用户态的切换等,开销相对较大)。await
来确保任务的正确执行顺序和依赖关系。3. 示例应用场景(网络爬虫)
import asyncio
import aiohttp
async def fetch(session, url):
async with session.get(url) as response:
return await response.text()
async def main():
async with aiohttp.ClientSession() as session:
urls = ["http://example.com", "http://python.org", "http://www.baidu.com"]
tasks = [fetch(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print(result[:100]) # 打印部分内容示例
asyncio.run(main())
在这个网络爬虫示例中,通过异步编程可以同时发起多个网页的请求,各个请求任务(协程)在等待服务器响应(I/O 操作)的过程中,事件循环会调度其他协程继续执行,等所有请求都有了结果后再统一处理,大大提高了爬取网页的效率。
二、Python 线程(基于threading
模块)
1. 概念
线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。在 Python 中,通过threading
模块来创建和管理线程。一个进程可以包含多个线程,这些线程共享进程的资源(如内存空间、文件描述符等),它们可以并发地执行不同的任务,操作系统会根据一定的调度算法来切换线程的执行,让每个线程都有机会使用 CPU 资源。
2. 特点
3. 示例应用场景(简单的多任务示例)
import threading
import time
def print_numbers():
for i in range(1, 6):
print(f"线程1: {i}")
time.sleep(1)
def print_letters():
for letter in ['a', 'b', 'c', 'd', 'e']:
print(f"线程2: {letter}")
time.sleep(1)
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_letters)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
在这个示例中,创建了两个线程分别执行不同的打印任务,它们可以并发地运行,在等待time.sleep
(模拟 I/O 操作)的时间里,操作系统会切换线程执行,从而实现两个任务看似 “同时” 进行的效果。
三、Python 进程(基于multiprocessing
模块)
1. 概念
进程是计算机中正在运行的程序的实例,它是操作系统进行资源分配和调度的基本单位。每个进程都有自己独立的内存空间、文件描述符等资源,进程之间相互独立,数据不共享(可以通过特定的进程间通信机制来交换数据)。在 Python 中,使用multiprocessing
模块来创建和管理多个进程。
2. 特点
3. 示例应用场景(利用多进程计算密集型任务)
import multiprocessing
import time
def square_numbers(numbers):
result = []
for num in numbers:
result.append(num ** 2)
return result
if __name__ == "__main__":
numbers = list(range(10))
processes = []
num_processes = multiprocessing.cpu_count() # 根据CPU核心数创建进程
chunk_size = len(numbers) // num_processes
for i in range(num_processes):
start = i * chunk_size
end = (i + 1) * chunk_size if i < num_processes - 1 else len(numbers)
p = multiprocessing.Process(target=square_numbers, args=([numbers[start:end]],))
processes.append(p)
p.start()
for p in processes:
p.join()
在这个示例中,将一个计算列表中数字平方的任务分配到多个进程中去执行,每个进程处理一部分数据,通过利用多核 CPU 实现并行计算,提高了计算密集型任务的执行效率。
四、三者对比
1. 资源开销
2. 并发能力
await
等机制)。3. 适用场景
作者:41楼的长颈鹿