# 知识点1:并发 vs 并行# ----------------------------------------------------------# · 并发(Concurrency):在一段时间内交替执行多个任务。# 单核 CPU 通过快速切换任务实现"看起来同时"的效果。# · 并行(Parallelism):在同一时刻真正同时执行多个任务。# 需要多核 CPU,每个核心独立运行一个任务。# · 类比:并发 = 一个人同时吃三个馒头,轮流咬;# 并行 = 三个人各吃一个馒头。# ----------------------------------------------------------# 知识点2:进程的概念# ----------------------------------------------------------# · 程序:保存在硬盘上的代码文件,是静态的(如 .py 文件)。# · 进程:程序被加载到内存中运行起来的实例,是动态的。# · 进程 = 操作系统进行资源分配和调度运行的基本单位。# · 每个进程拥有独立的内存空间,彼此不共享全局变量。# · 多进程适合 CPU 密集型任务(计算量大)。# ----------------------------------------------------------# 知识点3:__name__ 变量# ----------------------------------------------------------# · __name__ 是 Python 的内置变量,表示当前模块的名称。# · 当 .py 文件被直接运行时,__name__ = "__main__"# · 当 .py 文件被 import 导入时,__name__ = 文件名(不含 .py)# · 用途:区分"脚本直接运行"还是"被其他模块导入"。print(__name__) # 直接运行本文件时输出 "__main__"if __name__ == "__main__": # 知识点:这个 if 判断被称为"程序入口守卫"。 # 直接运行 → 条件满足,代码被执行 # 被 import → 条件不满足,代码被跳过(避免导入时意外执行) print("执行的为当前文件")# ----------------------------------------------------------# 知识点4:multiprocessing 模块# ----------------------------------------------------------# · Python 内置的跨平台多进程模块。# · 核心类:Process — 代表一个进程对象。# · 核心方法:# Process(target=函数名) → 创建进程对象,绑定目标函数# .start() → 启动进程(会在新进程中执行 target 函数)# .join() → 等待该进程结束(阻塞当前进程)# .is_alive() → 判断进程是否还在运行# import multiprocessing# import time## def sing():# for i in range(3):# print("sing")# time.sleep(1)## def dance():# for i in range(3):# print("dance")# time.sleep(1)## if __name__ == "__main__":# # 创建两个进程对象# sing_process = multiprocessing.Process(target=sing)# dance_process = multiprocessing.Process(target=dance)## # 启动进程:两个进程同时执行,互不阻塞# sing_process.start()# dance_process.start()## # 对比:直接调用函数则是串行执行# # sing() # 等 sing 执行完才能执行 dance# # dance()# ----------------------------------------------------------# 知识点5:多进程传参 — args 和 kwargs# ----------------------------------------------------------# · args:通过元组按位置传参,如 args=(4, "小明")# · kwargs:通过字典按关键字传参,如 kwargs={"num": 5, "name": "小红"}# · 二者可以同时使用:args 传位置参数,kwargs 传关键字参数。# · 注意:args 元组只有一个参数时,必须加逗号 args=(42,),# 否则 (42) 会被当作括号表达式而非元组。# import multiprocessing# import time## def sing(num, name):# for i in range(3):# print(f"{name} sing {num}")# time.sleep(1)## def dance(num, name):# for i in range(3):# print(f"{name} dance {num}")# time.sleep(1)## if __name__ == "__main__":# # 元组传参 (args),按位置匹配# sing_process = multiprocessing.Process(target=sing, args=(4, "小明"))# # 字典传参 (kwargs),按键名匹配# dance_process = multiprocessing.Process(# target=dance, kwargs={"num": 5, "name": "小红"}# )# sing_process.start()# dance_process.start()# ----------------------------------------------------------# 知识点6:进程编号 — os.getpid() 与 os.getppid()# ----------------------------------------------------------# · os.getpid() :获取当前进程的 ID(PID),操作系统唯一标识。# · os.getppid() :获取当前进程的父进程 ID。# · 主进程:执行 python 命令的那个进程。# · 子进程:由主进程通过 Process 创建出来的进程。# · 每个子进程的 ppid 就是主进程的 pid。# import multiprocessing# import time# import os## def work(num, name):# print(f"子进程 PID={os.getpid()}, 父进程 PPID={os.getppid()}")# for i in range(3):# print(f"{name} work {num}")# time.sleep(1)## if __name__ == "__main__":# print(f"主进程 PID={os.getpid()}")# p = multiprocessing.Process(target=work, args=(1, "任务"))# p.start()# ----------------------------------------------------------# 知识点7:守护进程 — daemon# ----------------------------------------------------------# · 默认行为:主进程会等待所有子进程执行完毕后才退出。# · 守护进程:主进程退出时,守护子进程会立即被终止,不管有没有执行完。# · 设置方式有两种(效果相同):# 方式一:Process(target=..., daemon=True) ← 构造时传入# 方式二:p.daemon = True ← 设置属性(必须在 start() 之前)# · 适用场景:后台日志、监控心跳、临时辅助任务(主任务结束就无需再跑)。# import multiprocessing# import time## def chat(num, name):# for i in range(num):# print(f"和 {name} 聊天")# time.sleep(0.2)## if __name__ == "__main__":# # 方式一:构造函数直接设置 daemon=True# # chat_process = multiprocessing.Process(target=chat, args=(10, "小明"), daemon=True)## # 方式二:先创建对象,再设置 daemon 属性(必须在 start() 之前设置)# chat_process = multiprocessing.Process(target=chat, args=(10, "小明"))# chat_process.daemon = True # 必须在 start() 之前设置,否则报错# chat_process.start()## time.sleep(1) # 主进程等 1 秒# print("主进程结束") # 主进程结束后,守护子进程自动终止# # 如果不设 daemon,即使打印了"主进程结束",子进程还会继续跑完 10 次# # 设置了 daemon 后,"主进程结束"打印后子进程立即消失# ----------------------------------------------------------# 知识点8(补充):进程不共享全局变量# ----------------------------------------------------------# · 每个子进程拥有独立的内存空间,全局变量不会在进程间共享。# · 子进程修改全局变量,主进程和其他子进程都看不到。# · 这是多进程与多线程的关键区别之一。# · 如需进程间通信,使用 Queue、Pipe、Manager 等。