Python实现美化版端口进程管理工具

 更新时间:2025年03月04日 08:49:18   作者:探客白泽  
这篇文章主要为大家详细介绍了如何使用Python实现一个美化版的端口进程管理工具,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

1. 简介

一个基于端口管理和进程管理的GUI工具,它可以显示当前系统上所有开放的端口信息,并且允许用户对选中的进程进行操作(如结束进程、定位进程文件夹路径、复制相关信息到剪贴板等)。

详细信息可参考原文信息:基于Python编写端口进程管理工具

2. 运行效果

3. 相关源码

import sys
import psutil
import os
import pyperclip
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem, QMenu, QAction, QComboBox, QLineEdit, QPushButton, QMessageBox, QHeaderView
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon

# 获取本机所有开放的端口及对应的进程信息
def get_open_ports():
    open_ports = []
    for conn in psutil.net_connections(kind='inet'):
        if conn.status != 'LISTEN':
            continue
        
        pid = conn.pid
        if conn.type == 1:  # TCP协议
            protocol = 'TCP'
        elif conn.type == 2:  # UDP协议
            protocol = 'UDP'
        else:
            protocol = 'N/A'
        
        try:
            process = psutil.Process(pid)
            process_name = process.name()
            exe_path = process.exe()
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            process_name = "N/A"
            exe_path = "N/A"
        
        open_ports.append({
            'Port': conn.laddr.port,
            'PID': pid,
            'Process Name': process_name,
            'Protocol': protocol,
            'Path': exe_path
        })
    
    return open_ports

# 根据端口号查询对应进程的信息
def search_by_port(port):
    open_ports = get_open_ports()
    for port_info in open_ports:
        if port_info['Port'] == port:
            return port_info
    return None

# 根据进程名称查询对应的端口信息
def search_by_process_name(name):
    open_ports = get_open_ports()
    result = []
    for port_info in open_ports:
        if name.lower() in port_info['Process Name'].lower():
            result.append(port_info)
    return result

# 根据PID查询对应的端口信息
def search_by_pid(pid):
    open_ports = get_open_ports()
    for port_info in open_ports:
        if port_info['PID'] == pid:
            return port_info
    return None

# 结束进程
def kill_process(pid):
    try:
        process = psutil.Process(pid)
        process.terminate()  # 发送 terminate 信号
        process.wait()  # 等待进程结束
        return True
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        return False

# 定位进程文件夹路径
def open_process_folder(exe_path):
    if exe_path and os.path.exists(exe_path):
        folder_path = os.path.dirname(exe_path)
        os.startfile(folder_path)  # 打开文件夹
        return True
    return False

# 复制到剪贴板的功能
def copy_to_clipboard(text):
    pyperclip.copy(text)  # 使用 pyperclip 库复制文本

class PortProcessManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("端口进程管理工具")
        self.setWindowIcon(QIcon(os.path.join(os.getcwd(), 'icon.ico')))
        self.setGeometry(100, 100, 900, 600)
        #self.setWindowOpacity(0.8)  # 设置窗口透明度为0.8
        
        # 主窗口布局
        self.main_widget = QWidget()
        self.setCentralWidget(self.main_widget)
        layout = QVBoxLayout(self.main_widget)

        # 搜索框布局
        search_layout = QHBoxLayout()
        
        self.search_type_combo = QComboBox()
        self.search_type_combo.addItems(["端口号", "进程名称", "PID"])
        self.search_type_combo.setCurrentIndex(0)
        search_layout.addWidget(self.search_type_combo)
        
        self.search_input = QLineEdit()
        search_layout.addWidget(self.search_input)
        
        self.search_button = QPushButton("查  询")
        self.search_button.clicked.connect(self.search)
        search_layout.addWidget(self.search_button)
        
        self.refresh_button = QPushButton("刷新列表")
        self.refresh_button.clicked.connect(self.refresh_list)
        search_layout.addWidget(self.refresh_button)

        layout.addLayout(search_layout)
        
        # 表格展示
        self.table = QTableWidget()
        self.table.setColumnCount(5)
        self.table.setHorizontalHeaderLabels(["PID", "协议", "端口", "进程名称", "相关路径"])
        self.table.setEditTriggers(QTableWidget.NoEditTriggers)  # 禁止编辑
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 列宽自适应
        layout.addWidget(self.table)

        # 右键菜单
        self.table.setContextMenuPolicy(Qt.CustomContextMenu)
        self.table.customContextMenuRequested.connect(self.open_right_menu)

        # 设置样式
        self.set_styles()

        # 初始化数据
        self.refresh_list()

    def set_styles(self):
        # 设置字体为 "Segoe UI"
        style = """
        * {
            font-family: "Segoe UI";
        }
        QPushButton {
            background-color: #2dd8e1;
            color: white;
            border: 1px solid #00a7c3;
            padding: 5px;
        }
        QHeaderView::section {
            background-color: #2dd8e1;
            color: white;
            padding: 5px;
        }
        """
        self.setStyleSheet(style)

    def refresh_list(self):
        self.table.setRowCount(0)
        open_ports = get_open_ports()
        if not open_ports:
            QMessageBox.information(self, "没有找到端口", "没有开放的端口或无法获取端口信息。")
            return
        for port_info in open_ports:
            row_position = self.table.rowCount()
            self.table.insertRow(row_position)
            self.table.setItem(row_position, 0, QTableWidgetItem(str(port_info['PID'])))
            self.table.setItem(row_position, 1, QTableWidgetItem(port_info['Protocol']))
            self.table.setItem(row_position, 2, QTableWidgetItem(str(port_info['Port'])))
            self.table.setItem(row_position, 3, QTableWidgetItem(port_info['Process Name']))
            self.table.setItem(row_position, 4, QTableWidgetItem(port_info['Path']))

    def search(self):
        search_value = self.search_input.text()
        search_type = self.search_type_combo.currentText()
        
        if not search_value:
            QMessageBox.warning(self, "输入错误", "请输入查询内容!")
            return
        
        self.table.setRowCount(0)
        if search_type == "端口号":
            try:
                port = int(search_value)
                port_info = search_by_port(port)
                if port_info:
                    self.add_row(port_info)
                else:
                    QMessageBox.information(self, "未找到", f"未找到端口 {port} 对应的进程。")
            except ValueError:
                QMessageBox.warning(self, "输入错误", "请输入有效的端口号。")
        elif search_type == "进程名称":
            result = search_by_process_name(search_value)
            if result:
                for port_info in result:
                    self.add_row(port_info)
            else:
                QMessageBox.information(self, "未找到", f"未找到进程名称包含 {search_value} 的记录。")
        elif search_type == "PID":
            try:
                pid = int(search_value)
                port_info = search_by_pid(pid)
                if port_info:
                    self.add_row(port_info)
                else:
                    QMessageBox.information(self, "未找到", f"未找到PID {pid} 对应的进程。")
            except ValueError:
                QMessageBox.warning(self, "输入错误", "请输入有效的PID。")

    def add_row(self, port_info):
        row_position = self.table.rowCount()
        self.table.insertRow(row_position)
        self.table.setItem(row_position, 0, QTableWidgetItem(str(port_info['PID'])))
        self.table.setItem(row_position, 1, QTableWidgetItem(port_info['Protocol']))
        self.table.setItem(row_position, 2, QTableWidgetItem(str(port_info['Port'])))
        self.table.setItem(row_position, 3, QTableWidgetItem(port_info['Process Name']))
        self.table.setItem(row_position, 4, QTableWidgetItem(port_info['Path']))

    def open_right_menu(self, pos):
        selected_item = self.table.itemAt(pos)
        if selected_item:
            row = selected_item.row()
            pid = self.table.item(row, 0).text()
            port = self.table.item(row, 2).text()
            process_name = self.table.item(row, 3).text()
            exe_path = self.table.item(row, 4).text()
            
            menu = QMenu(self)
            kill_action = QAction("结束进程", self)
            kill_action.triggered.connect(lambda: self.kill_process(int(pid)))
            menu.addAction(kill_action)

            folder_action = QAction("定位进程文件夹路径", self)
            folder_action.triggered.connect(lambda: self.open_folder(exe_path))
            menu.addAction(folder_action)

            copy_pid_action = QAction("复制PID", self)
            copy_pid_action.triggered.connect(lambda: copy_to_clipboard(pid))
            menu.addAction(copy_pid_action)

            copy_port_action = QAction("复制端口号", self)
            copy_port_action.triggered.connect(lambda: copy_to_clipboard(port))
            menu.addAction(copy_port_action)

            copy_process_action = QAction("复制进程名称", self)
            copy_process_action.triggered.connect(lambda: copy_to_clipboard(process_name))
            menu.addAction(copy_process_action)

            copy_path_action = QAction("复制相关路径", self)
            copy_path_action.triggered.connect(lambda: copy_to_clipboard(exe_path))
            menu.addAction(copy_path_action)

            menu.exec_(self.table.viewport().mapToGlobal(pos))

    def kill_process(self, pid):
        if kill_process(pid):
            QMessageBox.information(self, "结束进程", f"进程 (PID: {pid}) 已被成功结束。")
        else:
            QMessageBox.warning(self, "错误", "无法结束该进程,可能没有权限。")

    def open_folder(self, exe_path):
        if open_process_folder(exe_path):
            QMessageBox.information(self, "打开文件夹", "已成功定位进程文件夹。")
        else:
            QMessageBox.warning(self, "错误", "无法找到进程文件路径。")

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Return:  # 检测到回车键
            self.search()  # 执行查询操作
        else:
            super().keyPressEvent(event)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = PortProcessManager()
    window.show()
    sys.exit(app.exec_())

到此这篇关于Python实现美化版端口进程管理工具的文章就介绍到这了,更多相关Python端口进程管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python实现生成简单的Makefile文件代码示例

    Python实现生成简单的Makefile文件代码示例

    这篇文章主要介绍了Python实现生成简单的Makefile文件代码示例,本文给出了两段实现代码,需要的朋友可以参考下
    2015-03-03
  • Python列表推导式的使用方法

    Python列表推导式的使用方法

    这篇文章主要介绍了Python列表推导式的使用方法,大家参考使用吧
    2013-11-11
  • Python 图形绘制详细代码(一)

    Python 图形绘制详细代码(一)

    这篇文章主要介绍了Python 图形绘制详细代码,文章主要从最简单图像的开始,在同一图上绘制两条或多条线一些简单操作,想了解的小伙伴可以学习一下,希望对你的学习有所帮助
    2021-12-12
  • 在Python中使用sort()方法进行排序的简单教程

    在Python中使用sort()方法进行排序的简单教程

    这篇文章主要介绍了在Python中使用sort()方法进行排序的简单教程,是Python学习中的基础知识,需要的朋友可以参考下
    2015-05-05
  • Python数据可视化完全指南之Matplotlib+Seaborn+Plotly用法详解

    Python数据可视化完全指南之Matplotlib+Seaborn+Plotly用法详解

    本文详细介绍了Python数据可视化的三大主流库:Matplotlib、Seaborn与Plotly,涵盖折线图、柱状图、散点图等多种图表类型及美化技巧,希望帮助大家全面掌握数据可视化技能,提升数据呈现效果
    2026-05-05
  • 使用Django和Python创建Json response的方法

    使用Django和Python创建Json response的方法

    下面小编就为大家分享一篇使用Django和Python创建Json response的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Python 画出来六维图

    Python 画出来六维图

    这篇文章主要介绍了Python 画出来六维图,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • Elasticsearch映射字段数据类型及管理

    Elasticsearch映射字段数据类型及管理

    这篇文章主要介绍了Elasticsearch映射字段数据类型及管理的讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Python使用PyFiglet实现终端输出炫酷的ASCII艺术字效果

    Python使用PyFiglet实现终端输出炫酷的ASCII艺术字效果

    PyFiglet是一个基于Python的纯文本到ASCII艺术字转换工具,它实现了FIGlet的完整功能,本文给大家介绍了Python如何使用PyFiglet实现终端输出炫酷的ASCII艺术字效果,需要的朋友可以参考下
    2025-12-12
  • pytorch常用函数之torch.randn()解读

    pytorch常用函数之torch.randn()解读

    这篇文章主要介绍了pytorch常用函数之torch.randn()解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02

最新评论