使用python写一个程序,持续监控某个windows进程的活动信息,例如占用cpu比例、占用内存等
要持续监控某个Windows进程的活动信息,如CPU和内存占用,你可以使用psutil库。如果你还没有安装这个库,你可以使用pip进行安装:
pip install psutil
以下是一个简单的Python程序,用于持续监控特定进程(例如notepad.exe)的CPU和内存使用情况:
import psutil
import time
def find_process_by_name(name):
"""查找并返回具有给定名称的所有进程"""
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == name:
return proc.info['pid']
return None
def monitor_process(process_name, interval=1):
"""持续监控指定进程名的CPU和内存使用情况"""
while True:
pid = find_process_by_name(process_name)
if pid is None:
print(f"{process_name} 进程未找到.")
else:
p = psutil.Process(pid)
cpu_percent = p.cpu_percent(interval=0) # 0表示非阻塞模式,立即返回
memory_info = p.memory_info()
print(f"进程名: {process_name}, PID: {pid}, CPU占用: {cpu_percent}%, 内存占用: {memory_info.rss / (1024 ** 2)} MB")
time.sleep(interval)
if __name__ == "__main__":
process_name = "notepad.exe" # 你可以替换为你想监控的进程名
monitor_process(process_name)
注意:
该程序会无限循环地检查指定名称的进程,并打印其CPU和内存使用情况。你可以通过Ctrl+C来中断程序。
psutil.Process(pid).cpu_percent(interval=0)方法用于获取指定进程的CPU使用率。当interval为0时,它将返回一个非阻塞的CPU使用率估算值,这通常不如设置一个小的interval(例如0.1秒)来得准确,但在实时监控场景下可能更有用。
psutil.Process(pid).memory_info().rss返回进程占用的物理内存大小,单位是字节。在上面的代码中,我将其转换为了MB。
如果有多个同名的进程正在运行,该程序只会监控找到的第一个进程。如果你需要监控所有同名进程,可以稍微修改find_process_by_name函数来返回一个PID列表,并在monitor_process函数中遍历这个列表。
在上个程序基础上,添加功能,将占用信息输出到一个文件内,并且每一条信息前加上当前时间
为了将监控信息输出到一个文件,并在每条信息前加上当前时间,我们可以对之前的程序进行一些修改。下面是一个更新后的版本,它包含了将监控信息记录到文件的功能:
import psutil
import time
from datetime import datetime
def find_process_by_name(name):
"""查找并返回具有给定名称的进程PID"""
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == name:
return proc.info['pid']
return None
def monitor_process(process_name, log_file, interval=1):
"""持续监控指定进程名的CPU和内存使用情况,并记录到日志文件"""
with open(log_file, 'a') as f: # 使用'a'模式以追加方式写入文件
while True:
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 获取当前时间并格式化
pid = find_process_by_name(process_name)
if pid is None:
log_message = f"{current_time} - {process_name} 进程未找到.\n"
else:
p = psutil.Process(pid)
cpu_percent = p.cpu_percent(interval=0) # 非阻塞模式
memory_info = p.memory_info()
log_message = f"{current_time} - 进程名: {process_name}, PID: {pid}, CPU占用: {cpu_percent}%, 内存占用: {memory_info.rss / (1024 ** 2):.2f} MB\n"
f.write(log_message) # 写入日志
f.flush() # 确保日志被立即写入文件
print(log_message, end='') # 同时在控制台打印信息
time.sleep(interval)
if __name__ == "__main__":
process_name = "notepad.exe" # 替换为你想监控的进程名
log_file = "process_monitor.log" # 日志文件名
monitor_process(process_name, log_file)
在这个更新后的程序中,我们做了以下修改:
添加了一个log_file参数到monitor_process函数,用于指定日志文件的路径。
在函数内部,我们使用with open(log_file, ‘a’) as f:来以追加模式打开日志文件。这样,每次监控信息都会被追加到文件的末尾,而不是覆盖原有内容。
使用datetime.now().strftime(‘%Y-%m-%d %H:%M:%S’)来获取并格式化当前时间。
构造了一个包含当前时间和监控信息的日志消息log_message。
使用f.write(log_message)将日志消息写入文件,并使用f.flush()确保消息被立即写入磁盘。
同时,我们也使用print(log_message, end=‘’)将日志消息打印到控制台,以便实时查看。
现在,当你运行这个程序时,它会将监控信息记录到指定的日志文件中,并在每条信息前加上当前时间。
修改功能:需要监控所有同名进程
为了监控所有同名进程,我们需要修改程序来查找并监控所有匹配给定名称的进程,而不仅仅是第一个找到的进程。以下是修改后的程序:
import psutil
import time
from datetime import datetime
def find_processes_by_name(name):
"""查找并返回所有具有给定名称的进程的PID列表"""
pids = []
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] == name:
pids.append(proc.info['pid'])
return pids
def monitor_processes(process_name, log_file, interval=1):
"""持续监控所有同名进程的CPU和内存使用情况,并记录到日志文件"""
with open(log_file, 'a') as f: # 使用'a'模式以追加方式写入文件
while True:
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') # 获取当前时间并格式化
pids = find_processes_by_name(process_name)
if not pids:
log_message = f"{current_time} - 未找到名为 {process_name} 的进程.\n"
f.write(log_message)
else:
for pid in pids:
p = psutil.Process(pid)
try:
cpu_percent = p.cpu_percent(interval=0) # 非阻塞模式,可能需要调整interval以获得更准确的值
memory_info = p.memory_info()
log_message = (f"{current_time} - 进程名: {process_name}, PID: {pid}, "
f"CPU占用: {cpu_percent}%, 内存占用: {memory_info.rss / (1024 ** 2):.2f} MB\n")
f.write(log_message)
except psutil.NoSuchProcess:
# 进程可能在获取CPU和内存信息前已经结束
log_message = f"{current_time} - 进程名: {process_name}, PID: {pid} 已退出.\n"
f.write(log_message)
f.flush() # 确保日志被立即写入文件
print(f"已记录到日志文件: {log_file}")
time.sleep(interval)
if __name__ == "__main__":
process_name = "notepad.exe" # 替换为你想监控的进程名
log_file = "process_monitor.log" # 日志文件名
monitor_processes(process_name, log_file)
在这个修改后的版本中,我们更改了以下几个关键部分:
find_processes_by_name 函数现在返回一个PID列表,包含所有匹配给定名称的进程的PID。
monitor_processes 函数遍历这些PID,并对每个进程分别进行监控。
在尝试获取CPU和内存使用率之前,我们添加了一个异常处理块来捕获psutil.NoSuchProcess异常。这是因为在我们找到进程PID和实际获取其资源使用情况之间,进程可能已经退出。
日志记录现在会针对每个找到的进程分别进行。
请确保将process_name变量设置为你想要监控的进程名称,并且该程序需要有足够的权限来访问系统进程信息。
上面程序里cpu占用不准确,一直0%
如果你发现上面程序中的CPU占用率一直显示为0%,很可能是因为cpu_percent方法的interval参数没有正确设置。cpu_percent方法需要一个时间间隔来计算在该时间内的CPU使用率。如果将interval设置为0或非常短的时间,可能无法捕获到足够的CPU活动来计算准确的占用率。
为了解决这个问题,你可以在调用p.cpu_percent()时指定一个合理的interval值,比如interval=1(1秒)。这将给进程足够的时间来实际使用CPU,以便能够测量到非零的CPU占用率。
下面是修改后的代码片段,其中包含了interval参数的合理设置:
for pid in pids:
p = psutil.Process(pid)
try:
# 设置interval为1秒,以便有足够的时间来测量CPU占用率
cpu_percent = p.cpu_percent(interval=1)
memory_info = p.memory_info()
log_message = (f"{current_time} - 进程名: {process_name}, PID: {pid}, "
f"CPU占用: {cpu_percent}%, 内存占用: {memory_info.rss / (1024 ** 2):.2f} MB\n")
f.write(log_message)
except psutil.NoSuchProcess:
log_message = f"{current_time} - 进程名: {process_name}, PID: {pid} 已退出.\n"
f.write(log_message)
请注意,设置interval为1秒意味着每次测量CPU占用率时,程序都会等待1秒钟。这可能会影响程序的实时性,但会提高测量的准确性。你可以根据自己的需求调整interval的值,找到准确性和实时性之间的平衡。
另外,请确保你监控的进程在测量期间确实有CPU活动。如果进程处于休眠状态或没有执行任何计算任务,那么它的CPU占用率自然会很低或为零。你可以尝试让进程执行一些计算密集型任务,然后再次运行监控程序来检查CPU占用率是否仍然为零。