欢迎光临
我们一直在努力

第34课:Python|多进程、进程池、线程池原理与企业级实战用法

在这里插入图片描述

文章目录

  • 📖 开篇导读
  • 🎯 学习目标
  • 📚 知识点理论精讲
    • 一、多进程基础
      • 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(n1) + fib(n2)

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 从入门到精通》系列课程导航

去订阅

🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~

赞(0)
未经允许不得转载:171主机测评 » 第34课:Python|多进程、进程池、线程池原理与企业级实战用法
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址