Python 高级技巧:利用 psutil 和 subprocess 实现程序监控与管理

1.简介

在关键的应用程序中,监听程序的运行状态十分重要,因为其可以确保程序的平稳运行。本文将介绍如何使用Python实现这一功能,这里主要使用psutilsubprocess模块。同时,最后会提供一个完整的脚本案例供参考,用于监控并在目标程序意外停止时重启程序。

2.subprocess模块介绍

subprocess 模块是 Python 中用于创建和管理子进程的标准库模块。它允许你执行系统命令其他可执行文件,获取它们的输出,以及与其交互。下面是一些 subprocess 模块的基本用法和示例:

1. 运行外部命令

你可以使用 subprocess.run() 函数来运行外部命令,并等待其完成:

import subprocess

# 运行一个简单的命令
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)

# 打印命令输出
print(result.stdout)
  • ['ls', '-l'] 是一个示例命令,它列出当前目录的详细文件信息。
  • capture_output=True 表示捕获命令的标准输出和标准错误输出。
  • text=True 表示输出以文本字符串的形式返回,而不是字节。

2. 后台执行命令

如果你希望命令在后台执行而不阻塞当前进程,可以使用 subprocess.Popen 类:

import subprocess

# 后台执行命令
process = subprocess.Popen(['python', 'target.py'])

# 等待命令完成
process.wait()

3. 获取命令输出

如果需要获取命令的输出,可以使用 subprocess.check_output() 函数:

import subprocess

# 获取命令输出
output = subprocess.check_output(['echo', 'Hello, subprocess!'], text=True)

# 打印输出
print(output)

4. 传递输入给命令

有时候需要将数据传递给命令的标准输入。可以使用 subprocess.Popen.communicate() 方法来实现:

import subprocess

# 启动命令并传递输入
process = subprocess.Popen(['grep', 'Python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, text=True)

# 向命令输入数据
output, _ = process.communicate('Python is awesome!')

# 打印命令输出
print(output)

5. 处理命令返回值

通过 subprocess.run()subprocess.Popen.wait() 可以获取命令的返回值,通常是命令的退出代码。这可以帮助你判断命令是否成功执行。

3.psutil模块介绍

psutil(Python System and Process Utilities)模块是一个跨平台的库,提供了方便的接口来获取系统信息和管理进程。它可以用于监控系统资源的使用情况、管理进程以及执行系统管理任务。以下是 psutil 模块的一些主要功能和使用示例:

1. 安装 psutil

首先确保你已经安装了 psutil 模块。如果没有安装,可以通过 pip 安装:

pip install psutil

2. 获取系统信息

使用 psutil 可以轻松地获取系统的各种信息,如 CPU 使用率、内存使用情况、磁盘分区信息等。

import psutil

# 获取 CPU 逻辑核心数
cpu_count = psutil.cpu_count(logical=True)
print(f"CPU 逻辑核心数: {cpu_count}")

# 获取内存使用情况
memory = psutil.virtual_memory()
print(f"总内存: {memory.total / 1024 / 1024} MB")
print(f"已使用内存: {memory.used / 1024 / 1024} MB")

# 获取磁盘分区信息
disk_partitions = psutil.disk_partitions()
for partition in disk_partitions:
    print(f"分区设备: {partition.device}, 文件系统: {partition.fstype}")

3. 获取进程信息

psutil 可以用来获取系统中运行的进程信息,包括进程列表、CPU 使用率、内存使用情况等。

import psutil

# 获取所有进程列表
all_processes = list(psutil.process_iter())
for proc in all_processes[:5]:  # 打印前五个进程
    print(f"进程名: {proc.name()}, PID: {proc.pid}")

# 获取指定 PID 进程的详细信息
pid = 1234  # 替换成你要查看的进程 PID
if psutil.pid_exists(pid):
    process = psutil.Process(pid)
    print(f"进程名称: {process.name()}")
    print(f"进程状态: {process.status()}")
    print(f"进程创建时间: {process.create_time()}")
    print(f"进程 CPU 使用率: {process.cpu_percent(interval=1)}%")
    print(f"进程内存使用情况: {process.memory_info().rss / 1024 / 1024} MB")
else:
    print(f"PID {pid} 对应的进程不存在。")

4. 进程管理操作

psutil 还允许对进程进行管理操作,如终止进程、发送信号等。

import psutil

# 终止指定 PID 的进程
pid_to_terminate = 5678  # 替换成你要终止的进程 PID
if psutil.pid_exists(pid_to_terminate):
    process = psutil.Process(pid_to_terminate)
    process.terminate()
    print(f"进程 {pid_to_terminate} 已终止。")
else:
    print(f"PID {pid_to_terminate} 对应的进程不存在。")

5. 实时监控系统资源

使用 psutil 可以实现实时监控系统资源使用情况,例如在一个循环中获取 CPU 使用率:

import psutil

# 实时监控 CPU 使用率
while True:
    cpu_percent = psutil.cpu_percent(interval=1)
    print(f"当前 CPU 使用率: {cpu_percent}%")

这些示例展示了 psutil 模块在系统信息获取、进程管理和系统资源监控方面的基本用法。根据具体需求,你也可以进一步深入使用 psutil 的其他功能来实现更复杂的系统管理和监控任务。

4.实战应用

下面是一个使用subprocess模块来启动和监控一个Python程序的示例代码。后面将使用subprocess.Popen()来启动程序,并通过process.poll()来检查该进程是否仍在运行。如果目标程序停止运行,会获取其返回码,并根据返回码决定是否重新启动该程序。
具体代码如下所示:

import os
import subprocess
import sys
import time
import psutil  # 导入 psutil 模块


def start_target_program(target_script):
    # 显式指定Python解释器和环境变量
    python_executable = sys.executable
    env = dict(os.environ)
    env['PYTHONPATH'] = ":".join(sys.path)  # 将当前Python解释器的路径添加到PYTHONPATH环境变量中
    # 在这里启动你的Python程序
    return subprocess.Popen([python_executable, target_script], env=env)


def is_program_running(process):
    # 检查程序是否在运行
    return process.poll() is None


def bytes_to_readable(size_bytes):
    # 将字节数转换为可读的格式(KB、MB、GB)
    for unit in ['', 'KB', 'MB', 'GB']:
        if size_bytes < 1024.0:
            return f"{size_bytes:.2f} {unit}"
        size_bytes /= 1024.0


def monitor_process(target_script):
    # 启动被监测的程序
    target_program = start_target_program(target_script)
    while True:
        # 检查并打印 CPU 利用率
        cpu_percent = psutil.cpu_percent(interval=1)
        print(f"当前 CPU 利用率:{cpu_percent}%")

        # 获取并打印内存信息
        memory_info = psutil.virtual_memory()
        total_memory = bytes_to_readable(memory_info.total)
        available_memory = bytes_to_readable(memory_info.available)
        print(f"总内存: {total_memory}")
        print(f"可用内存: {available_memory}")

        # 获取并打印磁盘分区信息
        disk_partitions = psutil.disk_partitions()
        print("磁盘分区信息:")
        for partition in disk_partitions:
            print(f"    分区:{partition.device} 挂载点:{partition.mountpoint}")

        # 检查程序是否在运行
        if not is_program_running(target_program):
            # 检查程序结束状态(是否是正常结束)
            if target_program.returncode == 0:
                print("被监测的程序已正常关闭。")
                break
            else:
                print(f"被监测的程序已关闭,返回代码:{target_program.returncode}")
                print("重启中...")
                target_program = start_target_program(target_script)
        else:
            print("被监测的程序正常运行...")

        # 每隔10分钟监听一次
        time.sleep(600)


if __name__ == '__main__':
    # 需要注意被监控脚本的路径和监控程序保持在同一目录下
    target_script = input("请输入你需要监控的脚本名称(xxx.py):")
    monitor_process(target_script)

通过结合使用 subprocess 和 psutil 模块,可以轻松实现对目标程序的监控和管理。
本文提供了一个简单的示例代码,展示了如何启动、监控和重启一个程序。希望这能帮助你更好地理解和使用 Python 进行系统和进程管理。

你可能感兴趣的:(Python,python)