父进程 指的是创建并启动这个 music 子进程的那个进程。
1. 具体解释
python
import multiprocessing
import os
import time
def music(name, count):
print(f'p2进程, 进程id: {os.getpid()}, '
f'{multiprocessing.current_process().pid}, 父进程id: {os.getppid()}')
for i in range(1, count + 1):
time.sleep(0.1)
if __name__ == "__main__":
# 这是父进程
print(f"主进程(父进程)ID: {os.getpid()}")
# 创建子进程
p2 = multiprocessing.Process(target=music, args=("小明", 5))
p2.start()
p2.join()
输出示例:
主进程(父进程)ID: 12345
p2进程, 进程id: 12346, 12346, 父进程id: 12345
可以看到:
music进程的 PID 是 12346- 它的父进程 ID 是 12345,正是主进程
2. 进程树状关系
操作系统
└── Python解释器(主进程,PID: 12345)← 这是父进程
└── 子进程(music函数,PID: 12346)← 这是子进程
3. 验证父进程关系
python
import multiprocessing
import os
import time
def worker(name):
print(f"子进程 {name}:")
print(f" 自己的PID: {os.getpid()}")
print(f" 父进程PID: {os.getppid()}")
print(f" 父进程的父进程: {os.getppid()} 的父进程是?")
time.sleep(1)
if __name__ == "__main__":
print(f"主进程PID: {os.getpid()}")
# 创建子进程
p = multiprocessing.Process(target=worker, args=("A",))
p.start()
p.join()
# 验证:os.getppid() 在主进程中返回什么?
print(f"主进程的父进程PID: {os.getppid()}") # 这会是启动Python的shell/PID
4. 多级父子关系
python
import multiprocessing
import os
import time
def level2():
"""第二级子进程"""
print(f"第2级进程: PID={os.getpid()}, 父进程={os.getppid()}")
time.sleep(1)
def level1():
"""第一级子进程"""
print(f"第1级进程: PID={os.getpid()}, 父进程={os.getppid()}")
p = multiprocessing.Process(target=level2)
p.start()
p.join()
if __name__ == "__main__":
print(f"主进程(根父进程): PID={os.getpid()}")
p = multiprocessing.Process(target=level1)
p.start()
p.join()
输出:
主进程(根父进程): PID=100
第1级进程: PID=101, 父进程=100 ← 父进程是主进程
第2级进程: PID=102, 父进程=101 ← 父进程是第1级进程
进程树:
PID:100 (主进程)
└── PID:101 (level1子进程)
└── PID:102 (level2子进程)
5. 特殊情况和注意事项
情况1:孤儿进程
python
import multiprocessing
import os
import time
def orphan():
"""子进程的父进程结束后,成为孤儿进程"""
print(f"孤儿进程: PID={os.getpid()}, 父进程={os.getppid()}")
time.sleep(3) # 等待父进程结束
print(f"父进程结束后: PID={os.getpid()}, 新父进程={os.getppid()}")
# 父进程ID会变成1(init/systemd)或其他init进程
if __name__ == "__main__":
p = multiprocessing.Process(target=orphan)
p.start()
# 主进程快速结束,不等待子进程
print("主进程结束")
情况2:僵尸进程
python
import multiprocessing
import os
import time
def zombie():
print(f"子进程运行中: PID={os.getpid()}")
time.sleep(2)
if __name__ == "__main__":
p = multiprocessing.Process(target=zombie)
p.start()
time.sleep(1)
# 父进程没有调用 join(),子进程结束后可能变成僵尸
print(f"父进程: {os.getpid()}, 子进程结束但未回收")
# 应该调用 p.join() 来回收子进程
情况3:在不同操作系统上的行为
python
import multiprocessing
import os
import sys
def show_parent():
print(f"进程: {os.getpid()}, 父进程: {os.getppid()}")
if __name__ == "__main__":
print(f"Python PID: {os.getpid()}")
# Windows 和 Linux/Unix 上创建进程的方式不同
if sys.platform == 'win32':
print("Windows: 使用 spawn 方式创建进程")
else:
print("Linux/Unix: 使用 fork 方式创建进程")
p = multiprocessing.Process(target=show_parent)
p.start()
p.join()
6. 实际应用中的父进程概念
示例:进程池中的父进程
python
from multiprocessing import Pool
import os
def worker(x):
print(f"工作进程: {os.getpid()}, 父进程: {os.getppid()}")
return x * 2
if __name__ == "__main__":
print(f"主进程(父进程): {os.getpid()}")
# 创建进程池,子进程的父进程是主进程
with Pool(processes=3) as pool:
results = pool.map(worker, [1, 2, 3])
print(f"结果: {results}")
示例:守护进程
python
import multiprocessing
import os
import time
def daemon_worker():
"""守护进程:父进程结束后自动终止"""
print(f"守护进程启动: PID={os.getpid()}, 父进程={os.getppid()}")
try:
while True:
time.sleep(1)
print(f"守护进程运行中...")
except Exception as e:
print(f"守护进程被终止")
if __name__ == "__main__":
print(f"主进程: {os.getpid()}")
p = multiprocessing.Process(target=daemon_worker)
p.daemon = True # 设置为守护进程
p.start()
time.sleep(2)
print("主进程结束,守护进程也会自动结束")
7. 获取和管理父进程
python
import multiprocessing
import os
import signal
def child_process():
"""子进程可以获取父进程信息并与之交互"""
parent_pid = os.getppid()
print(f"子进程 {os.getpid()}, 父进程 {parent_pid}")
# 检查父进程是否还存活
try:
os.kill(parent_pid, 0) # 发送信号0测试进程是否存在
print("父进程还在运行")
except OSError:
print("父进程已经结束")
def parent_process():
"""父进程管理子进程"""
print(f"父进程: {os.getpid()}")
p = multiprocessing.Process(target=child_process)
p.start()
p.join()
# 父进程可以终止子进程
if p.is_alive():
p.terminate() # 发送终止信号
if __name__ == "__main__":
parent_process()
总结
- 父进程 = 创建并启动当前进程的进程
- 在
multiprocessing中,通常是主进程(if __name__ == "__main__"中的代码) - 使用
os.getppid()获取父进程 ID - 子进程可以通过父进程 ID 进行进程间通信和管理
- 当父进程结束时,子进程可能成为孤儿进程或被强制终止(守护进程)
- 正确管理父子进程关系对避免僵尸进程和资源泄漏很重要