本文目录导读:

Python案例:如何查看程序进程?从入门到实战,一文掌握进程监控技巧
目录导读
为什么需要查看程序进程?
在日常Python开发或运维中,我们经常遇到以下场景:
- 服务异常排查:某Python服务突然停止响应,需要确认进程是否还存在
- 资源监控:需要实时统计当前运行了哪些Python脚本及其CPU/内存占用
- 自动化运维:编写脚本定期检查特定进程是否存活,若不存活则自动重启
- 开发调试:想了解自己的代码是否创建了多个子进程,或是否有僵尸进程残留
进程是程序的一次动态执行实例,查看进程可以帮助开发者理解程序的运行状态、资源消耗以及与其他进程的关系,掌握Python中查看进程的方法,是进阶为合格后端工程师或DevOps工程师的必备技能。
基础篇:使用os模块查看当前进程信息
Python内置的os模块提供了一些基础的进程查询功能,主要适用于当前Python进程自身。
1 获取当前进程ID(PID)
import os
# 获取当前进程的PID
pid = os.getpid()
print(f"当前进程PID: {pid}")
# 获取当前进程父进程的PID
ppid = os.getppid()
print(f"父进程PID: {ppid}")
2 列出系统中所有进程(仅限Unix/Linux)
在Linux系统中,我们可以通过读取/proc文件系统来获取进程列表:
import os
def list_all_processes():
"""列出/proc下所有进程PID"""
pids = []
for entry in os.listdir('/proc'):
if entry.isdigit(): # 仅处理数字命名的目录(即PID)
pids.append(int(entry))
return sorted(pids)
print(f"当前系统共有 {len(list_all_processes())} 个进程")
局限性:os模块只能获取非常有限的进程信息(PID、PPID),无法获取进程名、CPU占用等详细数据,且跨平台性较差(Windows无法使用/proc)。
进阶篇:利用psutil库实现跨平台进程监控
psutil(Process and System Utilities)是Python生态中最强大的跨平台进程管理库,它支持Windows、Linux、macOS等主流系统。
1 安装psutil
pip install psutil
2 基础用法:获取所有进程列表
import psutil
# 获取所有进程详细信息
for proc in psutil.process_iter(['pid', 'name', 'status']):
try:
# 获取进程信息(dict格式)
info = proc.info
print(f"PID: {info['pid']}, 名称: {info['name']}, 状态: {info['status']}")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
3 更详细的进程信息查询
import psutil
# 通过PID获取单个进程对象
def get_process_detail(pid):
try:
p = psutil.Process(pid)
return {
"name": p.name(),
"exe": p.exe(), # 可执行文件路径
"cwd": p.cwd(), # 工作目录
"status": p.status(), # 运行状态
"cpu_percent": p.cpu_percent(interval=0.1), # CPU使用率
"memory_percent": p.memory_percent(), # 内存占用百分比
"create_time": p.create_time(), # 创建时间戳
"num_threads": p.num_threads(), # 线程数
"connections": p.connections() # 网络连接
}
except psutil.NoSuchProcess:
return None
# 示例:查看当前Python解释器进程
cur_pid = psutil.Process().pid
detail = get_process_detail(cur_pid)
if detail:
for key, val in detail.items():
print(f"{key}: {val}")
4 进程过滤与搜索
实际场景中,我们往往需要查找特定名称的进程,例如查找所有nginx进程:
import psutil
def find_processes_by_name(name):
"""通过进程名称查找所有匹配的进程"""
found = []
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
if proc.info['name'] == name or (proc.info['cmdline'] and name in ' '.join(proc.info['cmdline'])):
found.append(proc.info)
return found
# 查找Python进程
python_procs = find_processes_by_name("python3")
print(f"找到 {len(python_procs)} 个Python3进程:")
for p in python_procs[:5]: # 只显示前5个
print(f"PID: {p['pid']}, 命令行: {p['cmdline']}")
注意事项:psutil在查询部分系统进程时可能因权限不足抛出AccessDenied异常,建议用try-except包裹。
实战案例:监控Web服务进程并自动重启
假设我们有一个名为my_web_app.py的Flask服务,现在需要编写一个Python看门狗脚本,每10秒检查一次该服务是否在运行,如果挂了则自动重启。
1 完整的监控脚本
import psutil
import subprocess
import time
import logging
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
def is_process_running(process_name):
"""检查指定名称的进程是否在运行"""
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
# 优先匹配进程名,再检查命令行中是否包含关键词
cmdline = proc.info['cmdline']
if cmdline and process_name in ' '.join(cmdline):
logging.info(f"{process_name} 正在运行,PID: {proc.info['pid']}")
return True
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
return False
def restart_service(script_path):
"""重启服务"""
logging.warning(f"进程未找到,正在重启 {script_path}...")
try:
# 使用nohup在后台运行,避免被终端关闭影响
subprocess.Popen(
["nohup", "python3", script_path, "&"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
logging.info("服务已启动")
except Exception as e:
logging.error(f"重启失败: {e}")
if __name__ == "__main__":
APP_NAME = "my_web_app.py"
APP_PATH = "/home/user/my_web_app.py"
while True:
if not is_process_running(APP_NAME):
restart_service(APP_PATH)
time.sleep(10) # 每10秒检查一次
2 运行与测试
将此脚本保存为monitor.py,在终端运行:
python3 monitor.py &
此时即使my_web_app.py意外崩溃,监控脚本也会在10秒内重新启动它。
生产环境提示:更专业的方案是使用supervisor或systemd,但psutil方案适合嵌入式或临时监控场景。
常见问题与解答(Q&A)
Q1:为什么我用os.getpid()获取的PID和系统任务管理器看到的不一样?
A:os.getpid()获取的是当前Python进程的PID,它就是你运行的这个脚本自身的PID,如果你在交互式解释器里运行,那就是Python解释器进程;如果在脚本里运行,就是该脚本的进程,这与任务管理器显示的完全一致(除非你运行在多线程环境中)。
Q2: psutil在Windows上也能用吗?需要管理员权限吗?
A:可以,psutil完全支持Windows(包括Python for Windows),但某些操作(如终止系统进程、获取其他用户进程信息)需要管理员权限,建议在非管理员运行时用try-except捕获AccessDenied。
Q3: 如何区分多个同名但不同的Python脚本进程?
A:可以通过检查cmdline(命令行参数)来区分,两个脚本都叫python3,但一个命令行是python3 a.py,另一个是python3 b.py,利用'a.py' in cmdline即可区分,推荐结合psutil.Process(pid).cmdline()方法。
Q4: 进程查看对性能有影响吗?
A:频繁调用psutil(如每秒一次)会消耗少量CPU。psutil内部会读取/proc或系统API,相对高效,但如果要监控数百个进程且间隔小于1秒,建议考虑使用系统级工具(如top、htop)或采样方式。
Q5: 如果不安装第三方库,有没有纯内置的方案查看所有进程?
A:在Linux/Mac下可以通过os.popen('ps -aux')运行系统命令并解析输出,但不够优雅且跨平台差,在Windows上只能通过wmic或tasklist,同样需要解析字符串,因此psutil是最推荐的跨平台方案。
总结与最佳实践
- 明确需求:简单查看当前进程用
os.getpid()即可;需要监控系统所有进程请使用psutil。 - 警惕权限异常:
AccessDenied是常见问题,建议代码中做好异常处理。 - 避免过度CPU占用:监控进程时合理设置检查间隔(生产环境建议5-30秒)。
- 结合
cmdline精准匹配:进程名可能重复,通过命令参数可以定位到具体脚本。 - 日志记录:在自动化脚本中加入日志,便于后期排查。
核心回顾:
| 场景 | 推荐工具 | 优点 |
|------|----------|------|
| 获取当前进程PID | os.getpid() | 无需三方库,零依赖 |
| 查找特定名称进程 | psutil.process_iter() | 跨平台、功能全 |
| 获取内存/CPU详情 | psutil.Process() | 详细信息支持 |
| 自动化进程守护 | psutil + subprocess | 可自定义逻辑 |
通过本文的案例和代码,你已经能够从零开始用Python查看程序进程、监控服务状态并实现自动恢复,掌握这些技能后,无论是开发调试还是生产运维,都能事半功倍。
延伸阅读:如果想深入了解进程管理,建议学习subprocess模块(创建进程)、signal模块(进程信号处理)以及并发编程中的进程池概念。