
文章目录
- 📖 开篇导读
- 🎯 学习目标
- 📚 知识点理论精讲
-
- 一、多进程基础
-
- 1.1 为什么需要多进程?
- 1.2 创建进程
- 1.3 进程中的常用属性
- 二、进程间通信(IPC)
-
- 2.1 队列(`Queue`)
- 2.2 管道(`Pipe`)
- 2.3 共享内存(`Value`、`Array`)
- 2.4 管理器(`Manager`)
- 三、进程池(`Pool`)
-
- 3.1 基础使用
- 3.2 异步方法`apply_async`
- 3.3 批量异步:`starmap`和`starmap_async`
- 四、`concurrent.futures`:高级并发接口
-
- 4.1 线程池`ThreadPoolExecutor`
- 4.2 进程池`ProcessPoolExecutor`
- 4.3 优势
- 五、进程同步
- 六、多进程与多线程的选择指南
- 💻 代码案例实操
-
- 案例1:基础多进程与进程间通信(Queue)
- 案例2:使用Pipe双向通信
- 案例3:共享内存Value和Array加速计算
- 案例4:进程池Pool实现并行文件处理
- 案例5:使用`concurrent.futures`的线程池和进程池对比
- 案例6:进程池异步获取结果(apply_async)
- 案例7:Manager共享字典实现进程安全计数器
- 案例8:多进程爬取网页(模拟)
- ⚠️ 易错点避坑总结
- 📝 课后实战练习题
-
-
- 第1题:多进程计算素数
- 第2题:进程池批量处理图像(模拟)
- 第3题:生产者-消费者多进程版
- 第4题:使用`concurrent.futures`重构
- 第5题:多进程下载图片(真实或模拟)
- 第6题:矩阵乘法并行
- 第7题:使用Manager实现进程安全的计数器
-
- 🧠 知识点思维导图总结
- 🔜 下节课预告
-
- 第35课:协程、async/await异步编程零基础从入门到实战
- 🔗《50节课 Python 从入门到精通》系列课程导航
📖 开篇导读
在上一节课中,我们学习了多线程编程,了解了Python中由于GIL(全局解释器锁)的存在,多线程在计算密集型任务中无法利用多核CPU,甚至可能因为锁竞争而比单线程还慢。但是对于IO密集型任务(网络请求、文件读写等),多线程仍然有显著提升。
那么,如果我们需要处理CPU密集型任务(大数计算、图像处理、机器学习训练等),想要充分利用多核CPU,应该怎么办?答案是:多进程(Multiprocessing)。
多进程绕过GIL,每个进程拥有独立的Python解释器和内存空间,可以真正并行执行在多个CPU核心上。此外,Python还提供了**进程池(Pool)和线程池(ThreadPoolExecutor)**来简化并发任务的管理,是生产环境的推荐方式。
💡 工作场景:
- 数据处理:对大规模数据集进行并行计算(如MapReduce思想)。
- CI/CD:并行运行测试用例,减少构建时间。
- 爬虫:多进程下载不同站点的页面,充分利用带宽。
- Web后端:使用线程池处理大量IO请求(如Flask配合线程池)。
本课将学习:
- multiprocessing模块创建进程
- 进程间通信(Queue、Pipe、共享内存、Manager)
- 进程同步(锁、信号量等)
- 进程池Pool和apply_async、map方法
- concurrent.futures模块中的ThreadPoolExecutor和ProcessPoolExecutor
- 实战案例:并行文件处理、并行计算、多进程爬虫
学完本课,你将能够编写真正的并行程序,充分发挥多核CPU的性能。
🎯 学习目标
| 1️⃣ | 理解进程与线程的深层区别,掌握multiprocessing创建进程 | 突破GIL限制,利用多核 |
| 2️⃣ | 掌握进程间通信的多种方式(Queue、Pipe、共享内存、Manager) | 数据交换与同步 |
| 3️⃣ | 熟练使用进程池Pool进行任务批量处理 | 高效管理大量进程 |
| 4️⃣ | 熟练使用concurrent.futures中的线程池和进程池统一接口 | 简洁的并发编程 |
| 5️⃣ | 了解进程同步机制(Lock、Semaphore) | 避免资源竞争 |
| 6️⃣ | 能够根据任务类型选择多线程、多进程或异步IO | 架构设计能力 |
🔥 面试考点:“多进程和多线程的区别?”“什么是进程池?有什么用?”“multiprocessing.Pool的map和apply_async区别?”“共享内存的使用场景?”“如何实现进程安全的计数器?”
📚 知识点理论精讲
一、多进程基础
1.1 为什么需要多进程?
- 绕过GIL:每个进程有独立的GIL,可以真正的并行执行。
- 隔离性:进程崩溃不影响其他进程,稳定性更高。
- 劣势:创建和销毁进程开销大,进程间通信相对复杂。
1.2 创建进程
使用multiprocessing.Process,与threading.Thread用法类似。
from multiprocessing import Process
import os
def worker(name):
print(f"子进程 {name},PID: {os.getpid()}")
if __name__ == "__main__":
p = Process(target=worker, args=("A",))
p.start()
p.join()
注意:在Windows上必须将多进程代码放在if __name__ == "__main__":块内,否则会无限递归创建进程。
1.3 进程中的常用属性
- pid:进程ID
- name:进程名称
- daemon:是否守护进程(主进程结束时,子进程自动终止)
- join():等待进程结束
二、进程间通信(IPC)
由于进程内存独立,不能直接共享变量。Python提供了多种IPC机制。
2.1 队列(Queue)
multiprocessing.Queue类似于线程队列,但用于进程间安全传递数据。
from multiprocessing import Process, Queue
def producer(q):
q.put("Hello")
def consumer(q):
print(q.get())
if __name__ == "__main__":
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start(); p2.start()
p1.join(); p2.join()
2.2 管道(Pipe)
Pipe()返回两个连接对象,duplex=True表示双向通信。
from multiprocessing import Process, Pipe
def sender(conn):
conn.send("消息")
def receiver(conn):
msg = conn.recv()
print(msg)
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
p1 = Process(target=sender, args=(parent_conn,))
p2 = Process(target=receiver, args=(child_conn,))
p1.start(); p2.start()
p1.join(); p2.join()
2.3 共享内存(Value、Array)
用于共享简单数据类型或数组,效率高,但需要手动同步。
from multiprocessing import Process, Value, Array
def increment(val, arr):
val.value += 1
for i in range(len(arr)):
arr[i] += 1
if __name__ == "__main__":
v = Value('i', 0) # 'i'表示整数
a = Array('i', [0,0,0])
p = Process(target=increment, args=(v, a))
p.start()
p.join()
print(v.value, a[:])
2.4 管理器(Manager)
Manager提供了更高级的共享对象,如list、dict等,但性能较低。
from multiprocessing import Process, Manager
def add_data(d, key, value):
d[key] = value
if __name__ == "__main__":
with Manager() as manager:
d = manager.dict()
p = Process(target=add_data, args=(d, "name", "张三"))
p.start()
p.join()
print(d)
三、进程池(Pool)
频繁创建销毁进程开销大,进程池预先创建一批进程,重复使用。
3.1 基础使用
from multiprocessing import Pool
import time
def square(x):
return x * x
if __name__ == "__main__":
with Pool(processes=4) as pool:
results = pool.map(square, range(10))
print(results) # [0,1,4,9,16,25,36,49,64,81]
3.2 异步方法apply_async
用于非阻塞提交任务,返回AsyncResult对象。
def f(x):
return x * x
with Pool(4) as pool:
result = pool.apply_async(f, (10,))
print(result.get(timeout=1))
3.3 批量异步:starmap和starmap_async
starmap用于带多个参数的情况。
def add(x, y):
return x + y
with Pool(4) as pool:
results = pool.starmap(add, [(1,2), (3,4), (5,6)])
print(results) # [3,7,11]
四、concurrent.futures:高级并发接口
Python 3.2+ 提供了concurrent.futures模块,统一了线程池和进程池的API。
4.1 线程池ThreadPoolExecutor
from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
time.sleep(1)
return n * n
with ThreadPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(task, i) for i in range(10)]
results = [f.result() for f in futures]
4.2 进程池ProcessPoolExecutor
from concurrent.futures import ProcessPoolExecutor
def square(x):
return x * x
with ProcessPoolExecutor(max_workers=4) as executor:
results = list(executor.map(square, range(10)))
4.3 优势
- 统一的API,容易在进程池和线程池间切换。
- 使用as_completed等待最早完成的Future。
- 支持超时、回调等。
五、进程同步
类似于多线程,多进程也需要同步机制访问共享资源(尤其是Value和Array)。multiprocessing提供了Lock、RLock、Semaphore等。
from multiprocessing import Process, Lock, Value
def increment(v, lock):
for _ in range(1000):
with lock:
v.value += 1
if __name__ == "__main__":
v = Value('i', 0)
lock = Lock()
procs = [Process(target=increment, args=(v, lock)) for _ in range(10)]
for p in procs: p.start()
for p in procs: p.join()
print(v.value) # 10000
六、多进程与多线程的选择指南
| CPU密集型(计算、图像处理、机器学习) | 多进程(ProcessPoolExecutor) | 绕过GIL,利用多核 |
| IO密集型(网络请求、文件读写、数据库) | 多线程(ThreadPoolExecutor)或异步IO | 线程切换开销小,易编程 |
| 高并发、短任务 | 线程池 | 创建线程开销小 |
| 长期运行、计算量大 | 进程池 或 手动管理进程 | 稳定性好 |
💻 代码案例实操
案例1:基础多进程与进程间通信(Queue)
"""
basic_multiprocessing.py
演示创建多个进程,使用Queue传递数据
"""
from multiprocessing import Process, Queue
import os, time
def worker(q, name):
"""工作进程:从队列获取数据并处理"""
while True:
item = q.get()
if item is None:
break
print(f"进程 {name}(PID:{os.getpid()}) 处理 {item}")
time.sleep(0.5)
print(f"进程 {name} 退出")
def producer(q):
"""主进程产生任务"""
for i in range(10):
q.put(f"任务-{i}")
time.sleep(0.2)
# 发送结束信号
for _ in range(3): # 3个Worker
q.put(None)
if __name__ == "__main__":
q = Queue()
workers = []
for i in range(3):
p = Process(target=worker, args=(q, f"Worker{i+1}"))
workers.append(p)
p.start()
producer(q)
for p in workers:
p.join()
print("所有进程结束")
案例2:使用Pipe双向通信
"""
pipe_communication.py
父进程与子进程通过Pipe通信
"""
from multiprocessing import Process, Pipe
def child(conn):
"""子进程:接收命令,返回结果"""
while True:
cmd = conn.recv()
if cmd == "exit":
conn.send("bye")
break
elif cmd == "hello":
conn.send("world")
else:
conn.send(f"unknown command: {cmd}")
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
p = Process(target=child, args=(child_conn,))
p.start()
for cmd in ["hello", "ping", "exit"]:
parent_conn.send(cmd)
response = parent_conn.recv()
print(f"cmd: {cmd} -> response: {response}")
p.join()
案例3:共享内存Value和Array加速计算
"""
shared_memory.py
使用共享内存实现多进程并行累加
"""
from multiprocessing import Process, Value, Array, Lock
def add_partial(v, arr, start, end, lock):
"""计算部分和,并累加到共享变量"""
partial = sum(arr[start:end])
with lock:
v.value += partial
if __name__ == "__main__":
import random
n = 1000000
arr = Array('i', [random.randint(1,100) for _ in range(n)])
v = Value('i', 0)
lock = Lock()
num_processes = 4
chunk_size = n // num_processes
processes = []
for i in range(num_processes):
start = i * chunk_size
end = start + chunk_size
if i == num_processes – 1:
end = n
p = Process(target=add_partial, args=(v, arr, start, end, lock))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"并行计算总和: {v.value}")
print(f"实际总和: {sum(arr)}")
案例4:进程池Pool实现并行文件处理
"""
pool_file_process.py
使用进程池并行统计多个文件的行数
"""
from multiprocessing import Pool
import os
def count_lines(filename):
"""统计文件行数"""
if not os.path.exists(filename):
return (filename, –1)
with open(filename, 'r', encoding='utf-8') as f:
count = sum(1 for _ in f)
return (filename, count)
if __name__ == "__main__":
# 创建测试文件
for i in range(10):
with open(f"test_{i}.txt", "w") as f:
f.write("\\n".join(f"line{j}" for j in range(i*100)))
files = [f"test_{i}.txt" for i in range(10)]
with Pool(processes=4) as pool:
results = pool.map(count_lines, files)
for filename, lines in results:
print(f"{filename}: {lines}行")
# 清理
for i in range(10):
os.remove(f"test_{i}.txt")
案例5:使用concurrent.futures的线程池和进程池对比
"""
futures_compares.py
对比ThreadPoolExecutor和ProcessPoolExecutor处理CPU密集型任务
"""
import time
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
def fib(n):
"""计算Fibonacci数(递归版本,CPU密集)"""
if n < 2:
return n
return fib(n–1) + fib(n–2)
def run_threadpool(n, workers=4):
with ThreadPoolExecutor(max_workers=workers) as executor:
list(executor.map(fib, [n]*workers))
def run_processpool(n, workers=4):
with ProcessPoolExecutor(max_workers=workers) as executor:
list(executor.map(fib, [n]*workers))
if __name__ == "__main__":
n = 35 # 较大数,使计算明显
workers = 4
start = time.time()
run_threadpool(n, workers)
print(f"ThreadPoolExecutor耗时: {time.time() – start:.2f}s")
start = time.time()
run_processpool(n, workers)
print(f"ProcessPoolExecutor耗时: {time.time() – start:.2f}s")
案例6:进程池异步获取结果(apply_async)
"""
pool_async.py
使用apply_async进行非阻塞任务提交
"""
from multiprocessing import Pool
import time
def slow_square(x):
time.sleep(0.5)
return x * x
if __name__ == "__main__":
with Pool(4) as pool:
# 提交异步任务
async_results = [pool.apply_async(slow_square, (i,)) for i in range(10)]
# 可以继续做其他事情
print("任务已提交,等待结果…")
# 获取结果
for i, ar in enumerate(async_results):
# get()会阻塞直到结果就绪,可以设置超时
result = ar.get(timeout=10)
print(f"result[{i}] = {result}")
案例7:Manager共享字典实现进程安全计数器
"""
manager_dict_counter.py
使用Manager.dict协调多个进程修改字典
"""
from multiprocessing import Process, Manager
import time
def worker(d, lock, key, increment):
"""增加字典中key的值"""
for _ in range(100):
with lock:
d[key] = d.get(key, 0) + increment
time.sleep(0.001) # 模拟工作
if __name__ == "__main__":
with Manager() as manager:
d = manager.dict()
lock = manager.Lock() # 也可以使用multiprocessing.Lock
processes = []
for i in range(5):
p = Process(target=worker, args=(d, lock, "count", 1))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"最终计数: {d.get('count', 0)}") # 应为500
案例8:多进程爬取网页(模拟)
"""
parallel_webcrawler.py
使用进程池模拟并发请求多个URL(实际网络请求用多线程更好,此处仅演示)
"""
from multiprocessing import Pool
import time
import random
def fetch_url(url):
"""模拟请求网页,返回状态码"""
print(f"开始请求 {url}")
time.sleep(random.uniform(0.2, 0.8)) # 模拟网络延迟
status = 200 if random.random() > 0.1 else 404
print(f"完成 {url} -> {status}")
return (url, status)
if __name__ == "__main__":
urls = [
"https://example.com/page1",
"https://example.com/page2",
"https://example.com/page3",
"https://example.com/page4",
"https://example.com/page5",
]
with Pool(3) as pool:
results = pool.map(fetch_url, urls)
print("\\n结果汇总:")
for url, status in results:
print(f"{url}: {status}")
⚠️ 易错点避坑总结
| 1 | Windows下多进程代码未放在if __name__ == "__main__"内 | 无限递归创建进程,程序崩溃 | 所有多进程启动代码都在该块内 |
| 2 | 在进程间传递大对象(如大数据框架) | 序列化开销巨大,性能下降 | 尽量使用共享内存或mmap |
| 3 | 使用Queue时忘记处理空队列异常 | 导致进程阻塞或异常 | 使用get(timeout)或qsize()判断 |
| 4 | 多进程访问共享文件未加锁 | 文件内容错乱 | 使用文件锁或数据库 |
| 5 | 将多进程用于CPU密集型任务时等待结果不对 | 正确使用,但注意join | 等待所有进程结束再收集结果 |
| 6 | ProcessPoolExecutor提交任务过多导致内存爆炸 | 任务队列无限增长 | 使用max_workers限制,或分批提交 |
| 7 | 使用multiprocessing.Pool的map时,函数不能是lambda | 序列化失败 | 定义普通函数 |
| 8 | 在子进程中重新导入主模块导致无限循环 | Windows问题 | 同样需要保护主模块 |
| 9 | 共享Manager对象性能差 | 大量数据交换时慢 | 使用Queue或共享内存 |
| 10 | 进程中使用了非picklable对象(如文件句柄)作为参数 | pickle.PickleError | 传递路径字符串,在进程中自己打开 |
📝 课后实战练习题
第1题:多进程计算素数
编写程序,使用多进程计算1-1000000之间有多少个素数。拆分任务到4个进程,每个进程处理一部分,汇总结果。对比单进程耗时。
第2题:进程池批量处理图像(模拟)
假设有100张图片需要处理(每个图片处理耗时0.1秒),使用进程池(4个进程)处理,输出总耗时。模拟处理函数只需sleep。
第3题:生产者-消费者多进程版
使用multiprocessing.Queue实现一个多进程的生产者-消费者模型:一个生产者生产随机数,3个消费者处理(打印)。生产者生产20个数字后发送结束信号。
第4题:使用concurrent.futures重构
将第2题的进程池改成ProcessPoolExecutor实现,并比较代码简洁度。
第5题:多进程下载图片(真实或模拟)
模拟从URL列表下载图片,每个下载耗时随机。使用进程池下载,并统计成功率。注意:进程池不适合网络IO密集型,但可作为练习。
第6题:矩阵乘法并行
实现两个矩阵的乘法,将计算划分到多个进程中(按行划分)。较大矩阵如1000×1000,对比单进程和多进程时间。
第7题:使用Manager实现进程安全的计数器
定义一个Counter类,使用Manager的Value或dict实现。启动10个进程,每个进程增加计数器10000次,验证最终结果是否为100000。
🧠 知识点思维导图总结
#mermaid-svg-gNVHkhEvFXTgFdHX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-gNVHkhEvFXTgFdHX .error-icon{fill:#552222;}#mermaid-svg-gNVHkhEvFXTgFdHX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-gNVHkhEvFXTgFdHX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-gNVHkhEvFXTgFdHX .marker.cross{stroke:#333333;}#mermaid-svg-gNVHkhEvFXTgFdHX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-gNVHkhEvFXTgFdHX p{margin:0;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge{stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 text{fill:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth–1{stroke-width:17;}#mermaid-svg-gNVHkhEvFXTgFdHX .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-0{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-0{stroke-width:14;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-1{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-1{stroke-width:11;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 text{fill:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-2{stroke-width:8;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-3{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-3{stroke-width:5;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-4{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-4{stroke-width:2;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-5{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-5{stroke-width:-1;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-6{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-6{stroke-width:-4;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-7{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-7{stroke-width:-7;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-8{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-8{stroke-width:-10;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-9{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-9{stroke-width:-13;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 polygon,#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 text{fill:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .node-icon-10{font-size:40px;color:black;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .edge-depth-10{stroke-width:-16;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled circle,#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:lightgray;}#mermaid-svg-gNVHkhEvFXTgFdHX .disabled text{fill:#efefef;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-root rect,#mermaid-svg-gNVHkhEvFXTgFdHX .section-root path,#mermaid-svg-gNVHkhEvFXTgFdHX .section-root circle,#mermaid-svg-gNVHkhEvFXTgFdHX .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-gNVHkhEvFXTgFdHX .section-root text{fill:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-root span{color:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .section-2 span{color:#ffffff;}#mermaid-svg-gNVHkhEvFXTgFdHX .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-gNVHkhEvFXTgFdHX .edge{fill:none;}#mermaid-svg-gNVHkhEvFXTgFdHX .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-gNVHkhEvFXTgFdHX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
第34课:多进程与池
多进程基础
创建 Process
daemon 守护进程
join 等待
注意 Windows 使用 if name == 'main'
IPC
Queue 队列
Pipe 管道
Value/Array 共享内存
Manager 高级共享对象
进程池 Pool
批量 map / starmap
异步 apply_async
close / join
concurrent.futures
ThreadPoolExecutor
ProcessPoolExecutor
统一的 Future 接口
进程同步
Lock
RLock
Semaphore
选择指南
CPU密集 -> 多进程
IO密集 -> 多线程/异步
面试考点
多进程多线程区别
进程池优势
GIL对多进程无影响
Manager vs Queue
🔜 下节课预告
多进程和多线程都是并发编程的重要手段。随着异步编程的流行,Python还提供了asyncio库,使用协程实现高并发的IO任务。下一节课我们将学习协程与异步编程。
第35课:协程、async/await异步编程零基础从入门到实战
内容包括:
- 协程的概念与生成器的演进
- async/await语法
- 事件循环与asyncio库
- 异步IO与同步IO对比
- 实战:异步网络请求、Web爬虫
异步编程是高性能IO应用的核心,掌握它你将能写出高效的网络服务。
🌟 学习鼓励:多进程是Python突破GIL限制、充分利用多核CPU的利器。虽然多进程内存开销大,但通过进程池和共享内存可以高效管理。请务必亲手运行进程池和concurrent.futures的案例,体会两种API的区别和适用场景。多进程与多线程结合使用,能让你的程序性能成倍提升!
🔗《50节课 Python 从入门到精通》系列课程导航
去订阅
🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~

![[特殊字符]DeepSeek‑Harness(DSH)小白保姆教程-171主机测评](https://www.171host.com/wp-content/uploads/2026/08/20260816085112-6a817a009aabf-220x150.png)