使用 Python构建 Windows 进程管理器应用程序

在这篇博客中,我们将探讨如何使用 wxPython 构建一个简单的 Windows 进程管理器应用程序。这个应用程序允许用户列出当前系统上的所有进程,选择和终止进程,并将特定进程保存到文件中以供将来加载。

C:\pythoncode\new\manageprocess.py

全部代码

python 复制代码
import wx
import psutil
import os
import signal

class ProcessManager(wx.Frame):
    def __init__(self, parent, title):
        super(ProcessManager,self).__init__(parent, title=title, size=(800, 500))

        self.panel = wx.Panel(self)

        self.search_box = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSearchProcess, self.search_box)

        self.btn_list_processes = wx.Button(self.panel, label='List All Processes')

        # Create ListView1 with a checkbox column
        self.process_listview = wx.ListView(self.panel, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
        self.process_listview.InsertColumn(0, '', width=40)  # Checkbox column
        self.process_listview.InsertColumn(1, 'Process Name', width=200)
        self.process_listview.InsertColumn(2, 'PID', width=100)
        self.process_listview.InsertColumn(3, 'CPU %', width=100)
        self.process_listview.InsertColumn(4, 'RAM %', width=100)

        self.selected_listview = wx.ListView(self.panel, style=wx.LC_REPORT)
        self.selected_listview.InsertColumn(0, 'Process Name', width=200)
        self.selected_listview.InsertColumn(1, 'PID', width=100)

        self.btn_select_all = wx.Button(self.panel, label='Select All')
        self.btn_deselect_all = wx.Button(self.panel, label='Deselect All')
        self.btn_add_to_listview2 = wx.Button(self.panel, label='Add to ListView2')
        self.btn_kill_processes = wx.Button(self.panel, label='Kill Selected Processes')
        self.btn_kill_by_name = wx.Button(self.panel, label='Kill by Name')
        self.btn_save = wx.Button(self.panel, label='Save')
        self.btn_load = wx.Button(self.panel, label='Load')
        self.btn_delete_selected = wx.Button(self.panel, label='Delete Selected')

        # Organize layout with BoxSizers
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview1_sizer = wx.BoxSizer(wx.VERTICAL)
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview2_sizer = wx.BoxSizer(wx.VERTICAL)

        search_sizer.Add(self.search_box, 1, wx.EXPAND | wx.ALL, 5)
        search_sizer.Add(self.btn_list_processes, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(search_sizer, 0, wx.EXPAND | wx.ALL, 5)
        listview1_sizer.Add(self.process_listview, 1, wx.EXPAND | wx.ALL, 5)

        button_sizer.Add(self.btn_select_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_deselect_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_add_to_listview2, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)

        listview2_sizer.Add(self.selected_listview, 1, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_processes, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_by_name, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_save, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_load, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_delete_selected, 0, wx.EXPAND | wx.ALL, 5)

        main_sizer.Add(listview1_sizer, 1, wx.EXPAND | wx.ALL, 5)
        main_sizer.Add(listview2_sizer, 1, wx.EXPAND | wx.ALL, 5)

        self.panel.SetSizer(main_sizer)

        self.Bind(wx.EVT_BUTTON, self.OnListProcesses, self.btn_list_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcesses, self.btn_kill_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcessesByName, self.btn_kill_by_name)
        self.Bind(wx.EVT_BUTTON, self.OnSaveProcesses, self.btn_save)
        self.Bind(wx.EVT_BUTTON, self.OnLoadProcesses, self.btn_load)
        self.Bind(wx.EVT_BUTTON, self.OnSelectAll, self.btn_select_all)
        self.Bind(wx.EVT_BUTTON, self.OnDeselectAll, self.btn_deselect_all)
        self.Bind(wx.EVT_BUTTON, self.OnAddToListView2, self.btn_add_to_listview2)
        self.Bind(wx.EVT_BUTTON, self.OnDeleteSelected, self.btn_delete_selected)

        self.Show()

    def OnListProcesses(self,event):
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
            self.process_listview.SetItem(index, 1, proc.info['name'])
            self.process_listview.SetItem(index, 2, str(proc.info['pid']))
            self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
            self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnSearchProcess(self,event):
        search_query = self.search_box.GetValue().lower()
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            if search_query in proc.info['name'].lower():
                index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
                self.process_listview.SetItem(index, 1, proc.info['name'])
                self.process_listview.SetItem(index, 2, str(proc.info['pid']))
                self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
                self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnKillProcesses(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                pid = int(self.process_listview.GetItemText(i, 2))
                try:
                    os.kill(pid, signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {pid}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
        self.OnListProcesses(event)

    def OnKillProcessesByName(self,event):
        process_names = [self.selected_listview.GetItemText(i) for i in range(self.selected_listview.GetItemCount())]
        for proc in psutil.process_iter(['name', 'pid']):
            if proc.info['name'] in process_names:
                try:
                    os.kill(proc.info['pid'], signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {proc.info['pid']}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)

    def OnSaveProcesses(self,event):
        with open("processes.txt","w") as file:
            count = self.selected_listview.GetItemCount()
            for i in range(count):
                process_name = self.selected_listview.GetItemText(i)
                process_pid = self.selected_listview.GetItemText(i, 1)
                file.write(f"{process_name},{process_pid}\n")

    def OnLoadProcesses(self,event):
        self.selected_listview.DeleteAllItems()
        if os.path.exists("processes.txt"):
            with open("processes.txt","r") as file:
                for line in file:
                    process_name, process_pid = line.strip().split(',')
                    index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                    self.selected_listview.SetItem(index, 1, process_pid)

    def OnSelectAll(self,event): 
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)

    def OnDeselectAll(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.SetItemState(i, 0, wx.LIST_STATE_SELECTED)

    def OnAddToListView2(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                process_name = self.process_listview.GetItemText(i, 1)
                process_pid = self.process_listview.GetItemText(i, 2)
                index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                self.selected_listview.SetItem(index, 1, process_pid)

    def OnDeleteSelected(self,event):
        count = self.selected_listview.GetItemCount()
        for i in range(count - 1, -1, -1):
            if self.selected_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                self.selected_listview.DeleteItem(i)

if __name__ == "__main__":
    app = wx.App(False)
    frame = ProcessManager(None, "Process Manager")
    app.MainLoop()

项目概述

我们的目标是构建一个图形用户界面 (GUI) 应用程序,主要功能包括:

  1. 列出所有进程:列出当前系统上的所有进程,并显示进程名、PID、CPU 和内存占用情况。
  2. 搜索进程:通过输入框搜索指定进程名称,并显示匹配结果。
  3. 选择和终止进程:通过复选框选择多个进程并终止它们。
  4. 保存和加载进程列表:将选定的进程保存到文本文件中,并从文件加载这些进程。
  5. 进程管理:添加功能来按名称终止进程,并从列表中删除选中的项。

准备工作

在开始之前,确保你已经安装了 Python 和 wxPython。你可以通过以下命令安装 wxPython:

bash 复制代码
pip install wxPython

构建应用程序

下面是我们将要实现的完整代码。你可以直接复制到你的 IDE 中并运行。

python 复制代码
import wx
import psutil
import os
import signal

class ProcessManager(wx.Frame):
    def __init__(self, parent, title):
        super(ProcessManager, self).__init__(parent, title=title, size=(800, 500))

        self.panel = wx.Panel(self)

        # 搜索框
        self.search_box = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSearchProcess, self.search_box)

        # 列出所有进程按钮
        self.btn_list_processes = wx.Button(self.panel, label='List All Processes')

        # 创建 ListView1 并添加复选框列
        self.process_listview = wx.ListView(self.panel, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
        self.process_listview.InsertColumn(0, '', width=40)  # 复选框列
        self.process_listview.InsertColumn(1, 'Process Name', width=200)
        self.process_listview.InsertColumn(2, 'PID', width=100)
        self.process_listview.InsertColumn(3, 'CPU %', width=100)
        self.process_listview.InsertColumn(4, 'RAM %', width=100)

        self.selected_listview = wx.ListView(self.panel, style=wx.LC_REPORT)
        self.selected_listview.InsertColumn(0, 'Process Name', width=200)
        self.selected_listview.InsertColumn(1, 'PID', width=100)

        # 各种功能按钮
        self.btn_select_all = wx.Button(self.panel, label='Select All')
        self.btn_deselect_all = wx.Button(self.panel, label='Deselect All')
        self.btn_add_to_listview2 = wx.Button(self.panel, label='Add to ListView2')
        self.btn_kill_processes = wx.Button(self.panel, label='Kill Selected Processes')
        self.btn_kill_by_name = wx.Button(self.panel, label='Kill by Name')
        self.btn_save = wx.Button(self.panel, label='Save')
        self.btn_load = wx.Button(self.panel, label='Load')
        self.btn_delete_selected = wx.Button(self.panel, label='Delete Selected')

        # 使用 BoxSizers 组织布局
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview1_sizer = wx.BoxSizer(wx.VERTICAL)
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview2_sizer = wx.BoxSizer(wx.VERTICAL)

        # 将搜索框和按钮添加到布局中
        search_sizer.Add(self.search_box, 1, wx.EXPAND | wx.ALL, 5)
        search_sizer.Add(self.btn_list_processes, 0, wx.EXPAND | wx.ALL, 5)

        # 将 ListView1 和按钮添加到布局中
        listview1_sizer.Add(search_sizer, 0, wx.EXPAND | wx.ALL, 5)
        listview1_sizer.Add(self.process_listview, 1, wx.EXPAND | wx.ALL, 5)

        button_sizer.Add(self.btn_select_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_deselect_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_add_to_listview2, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)

        # 将 ListView2 和其他按钮添加到布局中
        listview2_sizer.Add(self.selected_listview, 1, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_processes, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_by_name, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_save, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_load, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_delete_selected, 0, wx.EXPAND | wx.ALL, 5)

        main_sizer.Add(listview1_sizer, 1, wx.EXPAND | wx.ALL, 5)
        main_sizer.Add(listview2_sizer, 1, wx.EXPAND | wx.ALL, 5)

        self.panel.SetSizer(main_sizer)

        # 绑定事件处理
        self.Bind(wx.EVT_BUTTON, self.OnListProcesses, self.btn_list_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcesses, self.btn_kill_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcessesByName, self.btn_kill_by_name)
        self.Bind(wx.EVT_BUTTON, self.OnSaveProcesses, self.btn_save)
        self.Bind(wx.EVT_BUTTON, self.OnLoadProcesses, self.btn_load)
        self.Bind(wx.EVT_BUTTON, self.OnSelectAll, self.btn_select_all)
        self.Bind(wx.EVT_BUTTON, self.OnDeselectAll, self.btn_deselect_all)
        self.Bind(wx.EVT_BUTTON, self.OnAddToListView2, self.btn_add_to_listview2)
        self.Bind(wx.EVT_BUTTON, self.OnDeleteSelected, self.btn_delete_selected)

        self.Show()

    def OnListProcesses(self, event):
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
            self.process_listview.SetItem(index, 1, proc.info['name'])
            self.process_listview.SetItem(index, 2, str(proc.info['pid']))
            self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
            self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnSearchProcess(self, event):
        search_query = self.search_box.GetValue().lower()
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            if search_query in proc.info['name'].lower():
                index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
                self.process_listview.SetItem(index, 1, proc.info['name'])
                self.process_listview.SetItem(index, 2, str(proc.info['pid']))
                self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
                self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnKillProcesses(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                pid = int(self.process_listview.GetItemText(i, 2))
                try:
                    os.kill(pid, signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {pid}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
        self.OnListProcesses(event)

    def OnKillProcessesByName(self, event):
        process_names = [self.selected_listview.GetItemText(i) for i in range(self.selected_listview.GetItemCount())]
        for proc in psutil.process_iter(['name', 'pid']):
            if proc.info['name'] in process_names:
                try:
                    os.kill(proc.info['pid'], signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {proc.info['pid']}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)

    def OnSaveProcesses(self, event):
        with open

('saved_processes.txt', 'w') as f:
            for i in range(self.selected_listview.GetItemCount()):
                process_name = self.selected_listview.GetItemText(i)
                process_pid = self.selected_listview.GetItemText(i, 1)
                f.write(f"{process_name},{process_pid}\n")

    def OnLoadProcesses(self, event):
        self.selected_listview.DeleteAllItems()
        try:
            with open('saved_processes.txt', 'r') as f:
                for line in f.readlines():
                    process_name, process_pid = line.strip().split(',')
                    index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                    self.selected_listview.SetItem(index, 1, process_pid)
        except FileNotFoundError:
            wx.MessageBox("No saved processes found.", "Error", wx.OK | wx.ICON_ERROR)

    def OnSelectAll(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.CheckItem(i)

    def OnDeselectAll(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.CheckItem(i, False)

    def OnAddToListView2(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.IsItemChecked(i):
                process_name = self.process_listview.GetItemText(i, 1)
                process_pid = self.process_listview.GetItemText(i, 2)
                index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                self.selected_listview.SetItem(index, 1, process_pid)

    def OnDeleteSelected(self, event):
        count = self.selected_listview.GetItemCount()
        for i in range(count - 1, -1, -1):
            if self.selected_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                self.selected_listview.DeleteItem(i)

if __name__ == "__main__":
    app = wx.App(False)
    frame = ProcessManager(None, "Process Manager")
    app.MainLoop()

代码解释

1. 初始化界面

ProcessManager 类的 __init__ 方法中,我们设置了窗口的基本布局,并添加了所有必要的控件,包括 ListView、按钮和搜索框。我们还绑定了所有按钮的事件处理方法。

2. 列出所有进程

OnListProcesses 方法中,我们使用 psutil.process_iter 获取所有正在运行的进程,并将它们显示在 ListView1 中。我们显示了进程名称、PID、CPU 使用率和内存使用率。

3. 搜索进程

OnSearchProcess 方法通过搜索框输入的内容进行过滤,并在 ListView1 中显示匹配的进程。

4. 选择和终止进程

我们可以使用复选框选择一个或多个进程,并通过 OnKillProcessesOnKillProcessesByName 方法终止它们。

5. 保存和加载进程列表

OnSaveProcesses 方法将选中的进程保存到一个文本文件中,而 OnLoadProcesses 方法则从文件加载这些进程并显示在 ListView2 中。

6. 全选和全不选

通过 OnSelectAllOnDeselectAll 方法,我们可以选择或取消选择 ListView1 中的所有项。

效果如下

总结

这个小型的进程管理器应用程序展示了如何使用 wxPython 构建一个功能强大的桌面应用。通过整合 psutil 和 wxPython,我们可以轻松地管理和监控系统进程,为用户提供了便捷的工具。

你可以进一步扩展这个应用程序,例如添加更多的进程管理功能,或者优化界面布局和用户体验。希望这篇博客对你有所帮助,并激发你在 Python 开发中的更多创意!

相关推荐
Jackson@ML22 分钟前
如何快速高效学习Python?
开发语言·python
聂 可 以1 小时前
推荐几个可以免费下载视频的软件(Neat Download Manager、蜗牛下载助手、bilidown)
windows·开源软件
UFIT2 小时前
Python函数与模块笔记
开发语言·python
言之。2 小时前
别学了,打会王者吧
java·python·mysql·容器·spark·php·html5
YiSLWLL2 小时前
使用Tauri 2.3.1+Leptos 0.7.8开发桌面小程序汇总
python·rust·sqlite·matplotlib·visual studio code
花酒锄作田3 小时前
[flask]自定义请求日志
python·flask
SsummerC4 小时前
【leetcode100】组合总和Ⅳ
数据结构·python·算法·leetcode·动态规划
Tandy12356_5 小时前
Godot开发2D冒险游戏——第一节:主角登场!
python·游戏引擎·godot
西柚小萌新6 小时前
【Python爬虫基础篇】--4.Selenium入门详细教程
爬虫·python·selenium
橘猫云计算机设计6 小时前
springboot基于hadoop的酷狗音乐爬虫大数据分析可视化系统(源码+lw+部署文档+讲解),源码可白嫖!
数据库·hadoop·spring boot·爬虫·python·数据分析·毕业设计