一、I/O 密集型任务处理
(一)理解 I/O 密集型任务
定义:I/O 密集型任务是指程序的大部分时间都用于等待输入 / 输出(I/O)操作完成,如文件读取、*请求、数据库查询等。例如,从*上下载一个大型文件,在等待数据传输的过程中,CPU 大部分时间是空闲的。
(二)多线程处理
原理:通过创建多个线程,当一个线程在等待 I/O 操作时,其他线程可以继续执行其他任务,从而提高程序的整体效率。在 Python 中,可以使用threading模块来实现多线程。示例代码:import threading
import time
def read_file(file_path):
# 模拟读取文件,这里使用了time.sleep来模拟I/O等待时间
print(f"开始读取文件: {file_path}")
time.sleep(3)
print(f"文件读取完成: {file_path}")
file_paths = ["file1.txt", "file2.txt", "file3.txt"]
threads = []
for file_path in file_paths:
t = threading.Thread(target=read_file, args=(file_path,))
t.start()
threads.append(t)
for t in threads:
t.join()在上述代码中,我们定义了一个read_file函数来模拟读取文件的操作。然后创建了多个线程来同时读取不同的文件,t.start()启动线程,t.join()用于等待所有线程完成。
(三)多进程处理
原理:多进程与多线程类似,但进程拥有自己独立的内存空间,对于一些需要更高隔离性和资源利用的场景更合适。在 Python 中,可以使用multiprocessing模块。示例代码:import multiprocessing
import time
def read_file(file_path):
print(f"开始读取文件: {file_path}")
time.sleep(3)
print(f"文件读取完成: {file_path}")
if __name__ == "__main__":
file_paths = ["file1.txt", "file2.txt", "file3.txt"]
processes = []
for file_path in file_paths:
p = multiprocessing.Process(target=read_file, args=(file_path,))
p.start()
processes.append(p)
for p in processes:
p.join()需要注意的是,在 Windows 系统下,使用multiprocessing模块时,if __name__ == "__main__"这一语句是必须的,以避免子进程无限递归创建进程。
(四)异步 I/O 处理
原理:异步 I/O 允许程序在等待 I/O 操作完成时不阻塞,可以继续执行其他任务。在 Python 中,asyncio库是处理异步 I/O 的重要工具。
示例代码:import asyncio
async def read_file_async(file_path):
print(f"开始读取文件: {file_path}")
await asyncio.sleep(3) # 模拟异步I/O等待
print(f"文件读取完成: {file_path}")
async def main():
file_paths = ["file1.txt", "file2.txt", "file3.txt"]
tasks = []
for file_path in file_paths:
task = read_file_async(file_path)
tasks.append(task)
await asyncio.gather(*tasks)
asyncio.run(main())在这个示例中,read_file_async函数是一个异步函数,await asyncio.sleep(3)模拟了异步 I/O 等待的过程。asyncio.gather函数用于同时运行多个异步任务。
二、组织异步代码结构
(一)分离关注点
含义:将不同的功能部分分离,例如,把 I/O 操作、数据处理、错误处理等部分分开编写。以*爬虫为例,一个模块负责发送 HTTP 请求(I/O 操作),另一个模块负责解析 HTML 数据(数据处理),还有一个模块负责记录错误。优点:这样的代码结构更清晰,便于维护和测试。如果 I/O 操作部分出现问题,只需要关注和修改这部分代码,而不会影响到其他部分。
(二)使用异步函数和协程
定义和使用:在 Python 的异步编程中,异步函数(用async def定义)返回的是一个协程对象。协程是一种轻量级的线程,可以在异步 I/O 环境中高效地运行。通过合理地定义和调用异步函数,可以构建出异步代码的执行流程。示例:import asyncio
async def getData():
# 模拟获取数据的异步操作
await asyncio.sleep(2)
return "Data"
async def processData(data):
# 模拟数据处理的异步操作
await asyncio.sleep(1)
print(f"处理数据: {data}")
async def main():
data = await getData()
await processData(data)
asyncio.run(main())