可用的网络接口:
\Device\NPF_{45C931DA-C83C-4AF1-A32E-8515B49A4F09}
\Device\NPF_{86FCE07C-A06F-416D-B784-D10CB0B53ECD}
\Device\NPF_{00A2F2C8-0041-4869-88A9-9E172A1755F8}
\Device\NPF_{6FA7FBD5-16B6-4A80-BB20-4B96652FFEE0}
\Device\NPF_{0B61559C-493D-458C-A155-CE87F09A88E0}
\Device\NPF_{2A954A09-58E5-43EE-96CE-583728C5E994}
\Device\NPF_{17AFF98A-37EA-417D-B479-15B682D2CD73}
\Device\NPF_Loopback
\Device\NPF_{14B9E7E3-6A72-40F2-AA6B-37061CA55397}
\Device\NPF_{22D68102-BAA8-4B48-B0A6-3BA1C0FA7229}
选择的接口: \Device\NPF_{45C931DA-C83C-4AF1-A32E-8515B49A4F09}
选择的接口: \Device\NPF_{0B61559C-493D-458C-A155-CE87F09A88E0}
选择的接口: \Device\NPF_{0B61559C-493D-458C-A155-CE87F09A88E0}
捕获数据包时出错: This event loop is already running
E:\PY\Python\流量\解决线程问题后\1.py:102: RuntimeWarning: coroutine 'Capture.packets_from_tshark' was never awaited
  print(f"捕获数据包时出错: {e}")
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
。。。。。。。。。
我下面的代码运行后出现上面的错误，怎么办，解决思路是什么，不用给出完整代码。

。。。。。。。。。。
import sys
import psutil
import pyshark
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QWidget,
    QTableWidget, QTableWidgetItem, QHeaderView, QComboBox,
    QHBoxLayout, QLabel, QLineEdit, QMessageBox
)
from PySide6.QtCore import Qt, QThread, Signal, QTimer, QSize,Signal
from PySide6.QtGui import QIcon, QPixmap
from collections import defaultdict
import win32gui
import win32ui
import win32con
from PIL import Image
import threading
import os
import ctypes
from scapy.all import get_if_list
from PyQt6.QtCore import QEventLoop
import asyncio
def make_transparent(image):
    image = image.convert("RGBA")
    datas = image.getdata()
    new_data = []
    for item in datas:
        if item[0] == 0 and item[1] == 0 and item[2] == 0:
            new_data.append((255, 255, 255, 0))
        else:
            new_data.append(item)
    image.putdata(new_data)
    return image

class NetworkMonitorThread(QThread):
    update_signal = Signal(list)

    def __init__(self, interface, parent=None):
        super().__init__(parent)
        self.running = True
        self.process_net_io = defaultdict(lambda: {'bytes_recv': 0, 'bytes_sent': 0, 'name': ''})
        self.lock = threading.Lock()
        self.interface = interface

    def run(self):
        if not self.interface:
            print("未选择网络接口，无法进行数据包捕获。")
            return

        try:
            # 创建 asyncio 事件循环
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)

            # 启动事件循环
            loop.run_until_complete(self.sniff_packets())

        except Exception as e:
            print(f"初始化数据包捕获时出错: {e}")
            return

        # 捕获结束后更新 UI
        self.update_ui()

    async def sniff_packets(self):
        try:
            loop = asyncio.get_event_loop()
            capture = pyshark.LiveCapture(interface=self.interface, bpf_filter='tcp or udp')

            while self.running:
                # 使用 asyncio.wait_for 来实现超时功能
                try:
                    packet = await asyncio.wait_for(capture.sniff(), timeout=1)
                except asyncio.TimeoutError:
                    continue  # 超时后继续下一次捕获

                if packet:
                    try:
                        if 'IP' in packet:
                            src_ip = packet.ip.src
                            dst_ip = packet.ip.dst
                            protocol = packet.transport_layer
                            src_port = packet[packet.transport_layer].srcport
                            dst_port = packet[packet.transport_layer].dstport
                            packet_length = int(packet.length)

                            # 查找与源 IP:port 相关的进程
                            src_pid = self.get_pid(src_ip, src_port, protocol)
                            if src_pid:
                                with self.lock:
                                    self.process_net_io[src_pid]['bytes_sent'] += packet_length

                            # 查找与目标 IP:port 相关的进程
                            dst_pid = self.get_pid(dst_ip, dst_port, protocol)
                            if dst_pid:
                                with self.lock:
                                    self.process_net_io[dst_pid]['bytes_recv'] += packet_length

                    except Exception as e:
                        print(f"处理数据包时出错: {e}")

        except Exception as e:
            print(f"捕获数据包时出错: {e}")

    def get_pid(self, ip, port, protocol):
        try:
            for proc in psutil.process_iter(['pid', 'name', 'connections']):
                for conn in proc.info['connections']:
                    if conn.laddr and conn.laddr.ip == ip and conn.laddr.port == int(port):
                        return proc.info['pid']
            return None
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            return None

    def update_ui(self):
        with self.lock:
            data = []
            for pid, io in self.process_net_io.items():
                if io['bytes_recv'] > 0 or io['bytes_sent'] > 0:
                    try:
                        proc = psutil.Process(pid)
                        name = proc.name()
                        data.append((
                            name,
                            io['bytes_recv'] / 1024,  # KB
                            io['bytes_sent'] / 1024,  # KB
                            io['bytes_recv'] / (1024 * 1024),  # MB
                            io['bytes_sent'] / (1024 * 1024)   # MB
                        ))
                    except (psutil.NoSuchProcess, psutil.AccessDenied):
                        continue
            # 重置统计
            self.process_net_io = defaultdict(lambda: {'bytes_recv': 0, 'bytes_sent': 0, 'name': ''})
            self.update_signal.emit(data)

    def stop(self):
        self.running = False
        if hasattr(self, 'capture'):
            self.capture.close()

            
class NetworkMonitor(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("网络流量监控")
        self.setGeometry(100, 100, 900, 600)

        self.table = QTableWidget(self)
        self.table.setColumnCount(6)
        self.table.setHorizontalHeaderLabels(["图标", "进程", "下载速度 (KB/s)", "上传速度 (KB/s)", "下载量 (MB)", "上传量 (MB)"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table.setIconSize(QSize(32, 32))

        layout = QVBoxLayout()
        layout.addWidget(self.table)

        # 接口选择部分
        interface_label = QLabel("选择网络接口:")
        self.interface_combo = QComboBox()
        self.interface_combo.currentIndexChanged.connect(self.change_interface)

        # 排序方式选择
        self.sort_combo = QComboBox()
        self.sort_combo.addItem("按下载速度排序")
        self.sort_combo.addItem("按进程名称排序")
        self.sort_combo.currentIndexChanged.connect(self.update_network_info)

        # 过滤输入框
        self.filter_input = QLineEdit(self)
        self.filter_input.setPlaceholderText("按进程名称过滤")
        self.filter_input.textChanged.connect(self.update_network_info)

        # 布局设置
        control_layout = QHBoxLayout()
        control_layout.addWidget(interface_label)
        control_layout.addWidget(self.interface_combo)
        control_layout.addSpacing(20)
        control_layout.addWidget(QLabel("排序方式:"))
        control_layout.addWidget(self.sort_combo)
        control_layout.addSpacing(20)
        control_layout.addWidget(QLabel("过滤:"))
        control_layout.addWidget(self.filter_input)
        layout.addLayout(control_layout)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        self.icon_cache = {}
        self.default_icon = QIcon("default_icon.png")  # 确保此路径有默认图标

        # 定时器，用于定期刷新表格
        self.ui_timer = QTimer()
        self.ui_timer.timeout.connect(self.refresh_table)
        self.ui_timer.start(2000)  # 每2秒刷新一次

        # 存储最新的数据
        self.latest_data = []

        # 初始化接口列表
        self.init_interfaces()

    

    def init_interfaces(self):
        interfaces = get_if_list()
        print("可用的网络接口:")
        for iface in interfaces:
            print(iface)

        # 过滤掉不需要的接口
        valid_interfaces = [iface for iface in interfaces if "Loopback" not in iface and "etwdump" not in iface]

        if not valid_interfaces:
            print("当前系统网络接口列表：", interfaces)  # 打印所有接口以帮助调试
            QMessageBox.critical(self, "错误", "未找到合适的网络接口进行捕获。")
            return

        # 如果有合适的接口，可以选择其中一个进行捕获
        #capture_interface = valid_interfaces[0]
        #print(f"选择的网络接口: {capture_interface}")
        # 接下来可以初始化捕获会话等




        # 添加接口到下拉框
        self.interface_combo.addItems(valid_interfaces)

        # 默认选择第一个接口并启动监控
        self.interface_combo.setCurrentIndex(4)
        self.start_monitoring(valid_interfaces[4])

    def change_interface(self, index):
        selected_interface = self.interface_combo.currentText()
        if selected_interface:
            self.start_monitoring(selected_interface)

    def start_monitoring(self, interface):
        # 停止已有的监控线程
        if hasattr(self, 'network_thread') and self.network_thread.isRunning():
            self.network_thread.stop()
            self.network_thread.wait()

        # 启动新的监控线程
        print(f"选择的接口: {interface}")
        self.network_thread = NetworkMonitorThread(interface, self)
        self.network_thread.update_signal.connect(self.update_table)
        self.network_thread.start()

    def update_table(self, sorted_data):
        self.latest_data = sorted_data

    def refresh_table(self):
        if not self.latest_data:
            return

        filter_text = self.filter_input.text().lower()
        filtered_data = [data for data in self.latest_data if filter_text in data[0].lower() or not filter_text]

        sort_by = self.sort_combo.currentIndex()
        if sort_by == 0:
            # 按下载速度排序
            filtered_data.sort(key=lambda x: x[1], reverse=True)
        else:
            # 按进程名称排序
            filtered_data.sort(key=lambda x: x[0])

        self.table.setRowCount(len(filtered_data))
        for row, data in enumerate(filtered_data):
            process_name = data[0]
            icon_item = QTableWidgetItem()
            icon = self.get_exe_icon(process_name)
            if icon:
                icon_item.setIcon(icon)
            else:
                icon_item.setIcon(self.default_icon)  # 使用默认图标
            self.table.setItem(row, 0, icon_item)

            # 设置进程名称
            self.table.setItem(row, 1, QTableWidgetItem(process_name))

            # 设置下载速度
            self.table.setItem(row, 2, QTableWidgetItem(f"{data[1]:.2f}"))

            # 设置上传速度
            self.table.setItem(row, 3, QTableWidgetItem(f"{data[2]:.2f}"))

            # 设置下载量
            self.table.setItem(row, 4, QTableWidgetItem(f"{data[3]:.2f}"))

            # 设置上传量
            self.table.setItem(row, 5, QTableWidgetItem(f"{data[4]:.2f}"))

    def get_exe_icon(self, process_name):
        if process_name in self.icon_cache:
            return self.icon_cache[process_name]

        try:
            exe_path = None
            for proc in psutil.process_iter(['pid', 'name', 'exe']):
                if proc.info['name'] == process_name:
                    exe_path = proc.info['exe']
                    break

            if not exe_path or not os.path.exists(exe_path):
                return None

            large, _ = win32gui.ExtractIconEx(exe_path, 0)
            if not large:
                return None

            hdc = win32gui.GetDC(0)
            hdc = win32ui.CreateDCFromHandle(hdc)
            hbmp = win32ui.CreateBitmap()
            hbmp.CreateCompatibleBitmap(hdc, 32, 32)

            hdc_mem = hdc.CreateCompatibleDC()
            hdc_mem.SelectObject(hbmp)
            win32gui.DrawIconEx(hdc_mem.GetSafeHdc(), 0, 0, large[0], 32, 32, 0, None, win32con.LR_ICON)

            bmpinfo = hbmp.GetInfo()
            bmpstr = hbmp.GetBitmapBits(True)
            img = Image.frombuffer(
                'RGB',
                (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
                bmpstr, 'raw', 'BGRX', 0, 1
            )

            img = make_transparent(img)
            img_path = f'temp_icon_{process_name}.png'
            img.save(img_path)
            pixmap = QPixmap(img_path)

            icon = QIcon(pixmap)
            self.icon_cache[process_name] = icon

            # 清理临时图标文件
            if os.path.exists(img_path):
                os.remove(img_path)

            return icon
        except Exception as e:
            print(f"提取图标时出错: {e}")
            return None

    def update_network_info(self):
        pass  # 排序和过滤逻辑已经在 refresh_table 中处理

    def closeEvent(self, event):
        if hasattr(self, 'network_thread') and self.network_thread.isRunning():
            self.network_thread.stop()
            self.network_thread.wait()
        super().closeEvent(event)

if __name__ == "__main__":
    # 检查是否以管理员身份运行
    try:
        is_admin = ctypes.windll.shell32.IsUserAnAdmin()
    except:
        is_admin = False

    if not is_admin:
        print("请以管理员身份运行此程序以获取完整的网络监控功能。")
        ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)
        sys.exit()

    app = QApplication(sys.argv)
    window = NetworkMonitor()
    window.show()
    sys.exit(app.exec())