re模块、sys模块、打印进度条、subprocess

本文介绍了Python的re模块,包括正则表达式的概念、常见匹配符号的使用,并提供了实例演示。接着讲解了sys模块的sys.path和sys.argv属性,展示了如何接收命令行参数。然后通过实例演示了如何实现打印进度条的功能。最后,探讨了subprocess模块的使用,展示如何执行系统命令并获取输出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

re模块

1.什么是正则

    正则就是用一系列具有特殊含义的字符组成的一套规则,该规则用来描述具有某一特征的字符串,正则就是用来去一个大的字符串中匹配出符合规则的子字符串

2.为什么要用正则

    1、用户注册
    2、爬虫程序

# print(re.findall('\w','hello 123_ */-='))
# print(re.findall('\W','hello 123_ */-='))
# print(re.findall('\s','hell\no 12\t3_ */-='))
# print(re.findall('\S','hell\no 12\t3_ */-='))
# print(re.findall('\d','hell\no 12\t3_ */-='))
# print(re.findall('\D','hell\no 12\t3_ */-='))
# print(re.findall('\n','hell\no 12\t3_ */-='))
# print(re.findall('\t','hell\no 12\t3_ */-='))
# print(re.findall('l','hell\no 12\t3_ */-='))


# print(re.findall('egon','my name is egon,egon is beautiful'))
#                                                      egon
# print(re.findall('^egon','egon my name is egon,egon is beautiful'))
# print(re.findall('egon$','egon my name is egon,egon is beautifulegon1'))

#                                                                egon

# 重复匹配
# .:匹配换行符以外的任意一个字符
# print(re.findall('a.c','abc a1c aac asd aaaaac a*c a+c abasd')) #['abc','a1c','aac','aac','a*c','a+c']
#                                                        a.c
# print(re.findall('a.c','abc a1c aac a\nc asd aaaaac a*c a+c abasd',re.DOTALL))


# []:匹配一个字符,该字符属于中括号内指定的字符
# print(re.findall('a..c','abc a1 c aac asd aaaaac a *c a+c abasd ='))
# print(re.findall('a.c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))
# print(re.findall('a[a-z]c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))
# print(re.findall('a[A-Z]c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))
# print(re.findall('a[-+*/]c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))
# print(re.findall('a[a-z][a-z]c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))
# print(re.findall('a[^a-z]c','abc a1 c aac aAc aBc asd aaaaac a-c a/c a *c a+c abasd = a1c a2c'))

# *: 必须与其他字符连用,代表左侧的字符出现0次或者无穷次
# print(re.findall('ab*','a ab abbb abbbb a1bbbb a-123'))
#                                              ab*
#['a','ab','abbb','abbbb','a','a']
# print(re.findall('ab{0,}','a ab abbb abbbb a1bbbb a-123'))


# ?: 必须与其他字符连用,代表左侧的字符出现0次或者1次
# print(re.findall('ab?','a ab abbb abbbb a1bbbb a-123'))
#                                              ab?
#['a','ab','ab','ab','a','a']
# print(re.findall('ab{0,1}','a ab abbb abbbb a1bbbb a-123'))


# +: 必须与其他字符连用,代表左侧的字符出现1次或者无穷次
# print(re.findall('ab+','a ab abbb abbbb a1bbbb a-123'))
#                                              ab+
# ['ab','abbb','abbbb']
# print(re.findall('ab{1,}','a ab abbb abbbb a1bbbb a-123'))


# {n,m}: 必须与其他字符连用
# print(re.findall('ab{1,3}','a ab abbb abbbb a1bbbb a-123'))
#                                                  ab{1,3}
# ['ab','abbb','abbb']


# .*:贪婪匹配
# print(re.findall('a.*c','ab123adfc1134124123adasfc123123'))

# .*?:非贪婪匹配
# print(re.findall('a.*?c','ab123adfc1134124123adasfc123123'))
#                                            a.*?c

#():分组
# print(re.findall('expression="(.*?)"','expression="1+2+3/4*5" egon="beautiful"'))
#                                       expression=".*?"

# print(re.findall('href="(.*?)"','<p>段落</p><a href="https://www.sb.com">点我啊</a><h1>标题</h1><a href="https://www.sb.com">点我啊</a>'))

#|:
# print(re.findall('a|b','ab123abasdfaf'))
#                        a|b

# print(re.findall('compan(?:ies|y)','Too many companies have gone bankrupt, and the next one is my company'))

#companies   company

# print(re.findall(r'a\\c','a\c a1c aAc aac'))
# print(re.findall('a\\\\c','a\c a1c aAc aac'))


# print(re.findall('ale(x)','alex is SB,alex is bigSB'))
# print(re.search('alex','alex is SB,alex is bigSB'))
# print(re.search('ale(x)','alex is SB,alex is bigSB').group()) #alex,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

# print(re.search('abcdefg','alex is SB,alex is bigSB'))

# print(re.search('^alex','123alex is SB,alex is bigSB'))
# print(re.match('alex','123alex is SB,alex is bigSB'))

# l='egon:18:male'.split(':')
# print(l)
# l1=re.split('[ :/-]','a-b/c egon:18:male xxx') #-因为有其特殊作用,只能放在首位或者末尾才能生效

# print(l1)

# print(re.sub('[a-z]+xx','yxp','lxx is good,sb is lllxx wxx is good cxx is good')) #sub为替换,将[a-z]+xx替换为yxp

#                                                   [a-z]+xx
结果:yxp is good,sb is yxp yxp is good yxp is good


pattern=re.compile('alex')
print(pattern.findall('alex is SB,alex is bigSB'))

 

print(pattern.search('alex is SB,alex is bigSB'))

 

02 sys模块

import sys
sys.path
sys.argv #用来接收Python解释器执行Py文件后跟的参数
#例如:python cp.py argv1 argv2 arg3
#sys.argv=['cp.py','argv1','argv2','argv3']

 

03 打印进度条

print('[%-50s]' %'#')
# print('[%-50s]' %'##')
# print('[%-50s]' %'###')
# print('[%-50s]' %'####')
# print('[%-50s]' %'#####')        从%s中拆分并添加功能-->%-50s,50为格数

 

# 1、控制打印进度条的宽度
# res='[%%-%ds]' %50   #第二个%号代表取消第一个%的特殊意义
# print(res %'#')
# print(res %'##')
# print(res %'###')
# print(res %'####')

# print(res %'#####')

#2、不换行+跳回行首打印
# import time
# print(('\r[%%-%ds]' %50) %'#',end='')   
# time.sleep(0.5)
# print(('\r[%%-%ds]' %50) %'##',end='')
# time.sleep(0.5)
# print(('\r[%%-%ds]' %50) %'###',end='')
# time.sleep(0.5)
# print(('\r[%%-%ds]' %50) %'####',end='')
# time.sleep(0.5)

# print(('\r[%%-%ds]' %50) %'#####',end='')

 

# 作业:打印进度条
# import time
#
# def make_progress(percent,width=50):
#     if percent > 1:percent=1
#     show_str=('[%%-%ds]' % width) % (int(percent * width) * '#')
#     print('\r%s %s%%' %(show_str,int(percent * 100)),end='')
#
# total_size=1025
# recv_size=0
# while recv_size < total_size:
#     time.sleep(0.1) # 模拟经过了0.5的网络延迟下载了1024个字节
#     recv_size+=1024
#     # 调用打印进度条的功能去打印进度条
#     percent=recv_size / total_size

#     make_progress(percent)

04 subprocess

# import os
# os.system('tasklist')


import subprocess
import time


obj=subprocess.Popen(
    'tasklist',
    shell=True, #固定格式
    stdout=subprocess.PIPE, #标准输出,与父程序的正确管道
    stderr=subprocess.PIPE #标准错误输出,与父程序的错误管道


)
# print(obj)
# stdout_res=obj.stdout.read()
# print(stdout_res.decode('gbk')) #将byte模式解码成gbk模式
# print(stdout_res)


stderr_res1=obj.stderr.read()
print(stderr_res1)  #没有结果
# stderr_res2=obj.stderr.read()
# stderr_res3=obj.stderr.read()
# print(stderr_res1.decode('gbk'))
# print(stderr_res1)
# print(stderr_res2)
# print(stderr_res3)


# import time
# time.sleep(50)

 

os.模块补充:

import os
# print(os.path.normcase('c:/WIndows\\system32\\')   )
结果:c:\windows\system32\
# print(os.path.normcase('c:/WIndows\\system32\\')   )
结果:c:\windows\system32\

sys模块

import sys
sys.path
sys.argv # 用来接收python解释器执行py文件后跟的参数
#例如:python cp.py argv1 argv2 arg3
sys.argv=['cp.py','argv1','argv2','argv3']

打印进度条演示:

import time

def make_progress(percent,width=50):
    if percent > 1:percent=1
    show_str=('[%%-%ds]' % width) % (int(percent * width) * '#')
    print('\r%s %s%%' %(show_str,int(percent * 100)),end='')

total_size=102400
recv_size=0
while recv_size < total_size:
    time.sleep(0.1) # 模拟经过了0.5s的网络延迟下载了1024个字节
    recv_size+=1024
    # 调用打印进度条的功能去打印进度条
    percent=recv_size / total_size
    make_progress(percent)

subprocess

# import os
# os.system('tasklist')

import subprocess
import time

obj=subprocess.Popen(
    'tasklist',
    shell=True, #固定格式
    stdout=subprocess.PIPE, #标准输出,与父程序的正确管道
    stderr=subprocess.PIPE #标准错误输出,与父程序的错误管道

)
# print(obj)
# stdout_res=obj.stdout.read()
# print(stdout_res.decode('gbk')) #将byte模式解码成gbk模式
# print(stdout_res)

stderr_res1=obj.stderr.read()
print(stderr_res1)  #没有结果
# stderr_res2=obj.stderr.read()
# stderr_res3=obj.stderr.read()
# print(stderr_res1.decode('gbk'))
# print(stderr_res1)
# print(stderr_res2)
# print(stderr_res3)

# import time
# time.sleep(50)

 

import os import sys import io import socket import time import re import threading import tkinter as tk import ttkbootstrap as tb import psutil import math import random import subprocess import json import queue from ttkbootstrap.constants import * from PIL import Image, ImageTk, ImageDraw # ====================== 数据采集服务 ====================== class HardwareMonitorService: def __init__(self): self.config = self.read_config() if self.config is None: raise Exception("配置读取失败,无法启动服务") self.server_ip = self.config.get('SERVER_IP') self.server_port = int(self.config.get('SERVER_PORT')) self.client_ip = self.config.get('CLIENT_IP') self.client_port = int(self.config.get('CLIENT_PORT')) self.running = True self.sock = None self.send_count = 1 self.setup_socket() # 启动服务线程 self.service_thread = threading.Thread(target=self.run_service, daemon=True) self.service_thread.start() def read_config(self): config = {} try: with open('config.txt', 'r') as config_file: for line in config_file: if '=' in line: key, value = line.strip().split('=', 1) config[key] = value print("读取配置成功", flush=True) return config except FileNotFoundError: print("无法打开配置文件!", flush=True) return None def is_command_available(self, command): """检查命令是否可用""" if os.name == 'nt': # Windows 系统 result = os.system(f'where {command} >nul 2>&1') else: # Linux 系统 result = os.system(f'which {command} >/dev/null 2>&1') return result == 0 def get_hardware_info(self, send_count): # 初始化硬件信息字典 hardware_data = { "cpu_temp": 0.0, "power": 0.0, "memory_used": 0, "memory_total": 0, "bandwidth": 0.0, "mlu_usage": 0.0, "cpu_usage": 0.0 } try: # 获取温度信息 result_temp = subprocess.run( ['cnmon', 'info', '-e'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1.0, check=True ).stdout.decode('utf-8') temp_match = re.search(r"Board\s*[::]?\s*([-+]?\d*\.?\d+)\s*[cC°]", result_temp) if temp_match: hardware_data["cpu_temp"] = float(temp_match.group(1)) # 获取功耗信息 result_power = subprocess.run( ['cnmon', 'info', '-p'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1.0, check=True ).stdout.decode('utf-8') power_match = re.search(r"Usage\s+:\s+(\d+\.?\d*)\s*W", result_power) if power_match: hardware_data["power"] = float(power_match.group(1)) # 获取内存信息 result_memory = subprocess.run( ['cnmon', 'info', '-m'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1.0, check=True ).stdout.decode('utf-8') mem_match = re.search(r"Used\s+:\s+(\d+)\s*MiB.*?Total\s+:\s+(\d+)\s*MiB", result_memory, re.DOTALL) if mem_match: hardware_data["memory_used"] = int(mem_match.group(1)) hardware_data["memory_total"] = int(mem_match.group(2)) # 获取带宽信息 result_bandwidth = subprocess.run( ['cnmon', 'info', '-b'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1.0, check=True ).stdout.decode('utf-8') bw_match = re.search(r"Bandwidth\s+:\s+([\d.]+)\s*GB/s", result_bandwidth) if bw_match: hardware_data["bandwidth"] = float(bw_match.group(1)) # 获取利用率信息 result_usage = subprocess.run( ['cnmon', 'info', '-u'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1.0, check=True ).stdout.decode('utf-8') mlu_match = re.search(r"MLU Average\s+:\s+(\d+) %", result_usage) if mlu_match: hardware_data["mlu_usage"] = float(mlu_match.group(1)) cpu_match = re.search(r"Device CPU Chip\s+:\s+(\d+) %", result_usage) if cpu_match: hardware_data["cpu_usage"] = float(cpu_match.group(1)) except Exception as e: print(f"硬件信息获取错误: {e}") # 返回模拟数据 return self.get_fallback_data(send_count) # 添加发送次数 hardware_data["send_count"] = send_count return json.dumps(hardware_data) def get_fallback_data(self, send_count): """返回全0数据""" return json.dumps({ "cpu_temp":0.0, "power": 0.0, "memory_used": 0, "memory_total": 0, "bandwidth": 0.0, "mlu_usage": 0.0, "cpu_usage": 0.0, "send_count": send_count }) def setup_socket(self): """设置UDP套接字""" try: # 创建 UDP 套接字 self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 端口号快速重用 self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 绑定服务器 IP 和端口 self.sock.bind((self.server_ip, self.server_port)) print(f"绑定到 {self.server_ip}:{self.server_port}", flush=True) except OSError as e: print(f"绑定错误: {e}", flush=True) self.running = False def run_service(self): print("硬件监控服务已启动", flush=True) while self.running: try: if not self.is_command_available('cnmon'): # 模拟数据 info = self.get_fallback_data(self.send_count) else: # 获取真实数据 info = self.get_hardware_info(self.send_count) # 发送JSON数据到客户端 self.sock.sendto(info.encode(), (self.client_ip, self.client_port)) self.send_count += 1 time.sleep(0.5) except Exception as e: print(f"服务错误: {e}", flush=True) time.sleep(1) def stop_service(self): """停止数据采集服务""" self.running = False if self.sock: self.sock.close() print("硬件监控服务已停止", flush=True) # ====================== GUI 监控界面 ====================== class EnhancedCircularProgressBar: def __init__(self, parent, size=200, thickness=20, bg_color="#1a1a1a", fg_color="#4caf50", text_color="#ffffff", font_size=16, title="", unit="", max_value=100, glow_effect=True): self.parent = parent self.size = size self.thickness = thickness self.bg_color = bg_color self.fg_color = fg_color self.text_color = text_color self.font_size = font_size self.title = title self.unit = unit self.max_value = max_value self.glow_effect = glow_effect # 创建Canvas self.canvas = tk.Canvas( parent, width=size, height=size, bg="black", highlightthickness=0, bd=0 ) # 计算圆心和半径 self.center_x = size / 2 self.center_y = size / 2 self.radius = (size - thickness) / 2 - 5 # 创建渐变效果 self.create_gradient() # 绘制背景圆环 self.draw_background() # 创建进度弧 self.arc_id = self.canvas.create_arc( self.center_x - self.radius, self.center_y - self.radius, self.center_x + self.radius, self.center_y + self.radius, start=90, extent=0, style=tk.ARC, outline="", width=thickness, tags="progress" ) # 创建发光效果 if self.glow_effect: self.glow_id = self.canvas.create_oval( self.center_x - self.radius - 5, self.center_y - self.radius - 5, self.center_x + self.radius + 5, self.center_y + self.radius + 5, outline="", fill="", tags="glow" ) # 创建文本元素 self.create_text_elements() # 动画控制变量 self.current_value = 0 self.target_value = 0 self.animation_running = False self.animation_id = None self.last_update_time = time.time() # 性能优化 self.canvas.tag_raise("progress") self.canvas.tag_raise("text") def create_gradient(self): """创建渐变背景效果""" self.gradient_img = Image.new("RGBA", (self.size, self.size), (0, 0, 0, 0)) draw = ImageDraw.Draw(self.gradient_img) for r in range(int(self.radius), 0, -1): alpha = int(150 * (1 - r/self.radius)) draw.ellipse([ self.center_x - r, self.center_y - r, self.center_x + r, self.center_y + r ], outline=(40, 40, 40, alpha)) self.gradient_photo = ImageTk.PhotoImage(self.gradient_img) self.canvas.create_image( self.center_x, self.center_y, image=self.gradient_photo, tags="background" ) def draw_background(self): """绘制背景圆环""" self.bg_arc_id = self.canvas.create_arc( self.center_x - self.radius, self.center_y - self.radius, self.center_x + self.radius, self.center_y + self.radius, start=0, extent=359.9, style=tk.ARC, outline=self.bg_color, width=self.thickness, tags="background" ) def create_text_elements(self): """创建所有文本元素""" # 标题文本 self.title_id = self.canvas.create_text( self.center_x, self.center_y - self.radius * 0.5, text=self.title, fill=self.text_color, font=("Arial", self.font_size, "bold"), tags="text" ) # 数值文本 self.value_id = self.canvas.create_text( self.center_x, self.center_y, text="0", fill=self.text_color, font=("Arial", int(self.font_size * 1.8), "bold"), tags="text" ) # 单位文本 self.unit_id = self.canvas.create_text( self.center_x, self.center_y + self.radius * 0.3, text=self.unit, fill=self.text_color, font=("Arial", self.font_size - 2), tags="text" ) def calculate_color(self, value): """实现绿→黄→橙→红颜色过渡""" ratio = value / self.max_value if ratio <= 0.5: # 绿(0,255,0) → 黄(255,255,0) r = int(510 * ratio) g = 255 b = 0 elif ratio <= 0.75: # 黄(255,255,0) → 橙(255,165,0) r = 255 g = int(255 - 360 * (ratio - 0.5)) # 255 → 165 b = 0 else: # 橙(255,165,0) → 红(255,0,0) r = 255 g = int(165 - 660 * (ratio - 0.75)) # 165 → 0 b = 0 return f"#{r:02x}{g:02x}{b:02x}" def set_value(self, value): """设置目标值""" self.target_value = max(0, min(self.max_value, value)) # 更新数值显示 self.canvas.itemconfig(self.value_id, text=f"{self.target_value:.1f}") # 启动动画 if not self.animation_running: self.animate() def animate(self): """平滑动画更新进度""" self.animation_running = True # 计算插值(使用缓动函数) delta = self.target_value - self.current_value speed_factor = 0.2 # 控制动画速度 if abs(delta) > 0.1: self.current_value += delta * speed_factor else: self.current_value = self.target_value # 计算弧的角度 angle = 360 * (self.current_value / self.max_value) # 更新弧 self.canvas.itemconfig(self.arc_id, extent=-angle) # 更新颜色 color = self.calculate_color(self.current_value) self.canvas.itemconfig(self.arc_id, outline=color) # 更新发光效果 if self.glow_effect and time.time() - self.last_update_time > 0.1: self.update_glow_effect(color) self.last_update_time = time.time() # 继续动画或停止 if abs(self.current_value - self.target_value) > 0.5: self.animation_id = self.canvas.after(16, self.animate) else: self.current_value = self.target_value self.animation_running = False self.animation_id = None def update_glow_effect(self, color): """更新发光效果""" if not self.glow_effect: return # 创建新的发光图像 glow_img = Image.new("RGBA", (self.size, self.size), (0, 0, 0, 0)) draw = ImageDraw.Draw(glow_img) # 解析颜色 r = int(color[1:3], 16) g = int(color[3:5], 16) b = int(color[5:7], 16) # 绘制发光效果 for i in range(1, 6): alpha = int(50 * (1 - i/6)) radius = self.radius + i draw.ellipse([ self.center_x - radius, self.center_y - radius, self.center_x + radius, self.center_y + radius ], outline=(r, g, b, alpha), width=1) self.glow_photo = ImageTk.PhotoImage(glow_img) self.canvas.itemconfig(self.glow_id, image=self.glow_photo) def reset(self): """重置进度条""" if self.animation_id: self.canvas.after_cancel(self.animation_id) self.current_value = 0 self.target_value = 0 self.canvas.itemconfig(self.arc_id, extent=0) self.canvas.itemconfig(self.value_id, text="0") color = self.calculate_color(0) self.canvas.itemconfig(self.arc_id, outline=color) class SystemMonitorApp: def __init__(self): # 启动数据采集服务 try: self.monitor_service = HardwareMonitorService() client_ip = self.monitor_service.client_ip client_port = self.monitor_service.client_port except Exception as e: print(f"无法启动数据采集服务: {e}") self.monitor_service = None client_ip = "127.0.0.1" client_port = 9999 # 创建主窗口 self.root = tb.Window(themename="darkly", title="系统资源监控", size=(1300, 800)) self.root.iconbitmap("") self.root.minsize(1000, 700) # 设置样式 style = tb.Style() style.configure("TFrame", background="#121212") style.configure("Title.TLabel", background="#121212", foreground="#e0e0e0", font=("Arial", 16, "bold")) # 创建UDP接收套接字 self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.udp_socket.bind((client_ip, client_port)) print(f"GUI绑定到 {client_ip}:{client_port} 接收数据") except Exception as e: print(f"GUI绑定错误: {e}") self.udp_socket.settimeout(0.1) # 设置超时避免阻塞 # 存储真实数据的变量 self.real_data = { "cpu_temp": 0.0, "power": 0.0, "memory": 0.0, # 内存使用百分比 "bandwidth": 0.0, # 带宽,单位GB/s "mlu_usage": 0.0, "cpu_usage": 0.0 } # 数据更新队列(用于线程安全) self.data_queue = queue.Queue() # 创建主框架 - 改为水平分割布局 main_frame = tb.Frame(self.root, padding=10) main_frame.pack(fill=tk.BOTH, expand=True) # ========== 左侧控制面板 ========== left_panel = tb.Frame(main_frame, width=220, padding=10) left_panel.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10)) # 下拉选项按钮 tb.Label(left_panel, text="选择监控设备", bootstyle=PRIMARY).pack(anchor=tk.W, pady=(0, 5)) self.device_var = tk.StringVar() device_options = ["设备A", "设备B", "设备C", "设备D"] device_combo = tb.Combobox( left_panel, textvariable=self.device_var, values=device_options, state="readonly", bootstyle=PRIMARY ) device_combo.pack(fill=tk.X, pady=(0, 20)) device_combo.current(0) # 设置默认选项 # 其他控制选项 tb.Label(left_panel, text="监控设置", bootstyle=PRIMARY).pack(anchor=tk.W, pady=(10, 5)) # 采样频率滑块 self.sampling_rate = tk.IntVar(value=1) tb.Label(left_panel, text="采样频率(秒):").pack(anchor=tk.W) tb.Scale( left_panel, from_=0.5, to=5, length=180, orient=tk.HORIZONTAL, variable=self.sampling_rate, bootstyle=PRIMARY ).pack(fill=tk.X, pady=(0, 15)) # 报警阈值设置 tb.Label(left_panel, text="温度报警阈值(°C):").pack(anchor=tk.W) self.temp_threshold = tk.IntVar(value=80) tb.Entry( left_panel, textvariable=self.temp_threshold, width=10, bootstyle=PRIMARY ).pack(fill=tk.X, pady=(0, 15)) # 控制按钮 control_frame = tb.Frame(left_panel) control_frame.pack(fill=tk.X, pady=(10, 0)) tb.Button( control_frame, text="启动", bootstyle=SUCCESS, command=self.start_monitoring ).pack(side=tk.LEFT, padx=2) tb.Button( control_frame, text="暂停", bootstyle=DANGER, command=self.stop_monitoring ).pack(side=tk.LEFT, padx=2) tb.Button( control_frame, text="重置", bootstyle=WARNING, command=self.reset_all ).pack(side=tk.LEFT, padx=2) # 状态指示器 tb.Label(left_panel, text="连接状态", bootstyle=PRIMARY).pack(anchor=tk.W, pady=(15, 5)) self.status_indicator = tb.Label( left_panel, text="● 已连接", bootstyle=(SUCCESS, INVERSE), font=("Arial", 10) ) self.status_indicator.pack(fill=tk.X, pady=(0, 5)) # ========== 右侧监控面板 ========== right_panel = tb.Frame(main_frame) right_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) # 标题 tb.Label( right_panel, text="系统资源实时监控", style="Title.TLabel" ).pack(pady=(0, 15)) # 创建进度条容器框架 progress_container = tb.Frame(right_panel) progress_container.pack(fill=tk.BOTH, expand=True, pady=5) # 创建监控指标配置 (保持不变) monitor_config = [ {"title": "CPU温度", "unit": "°C", "max_value": 100, "thickness": 18, "fg_color": "#ff5555"}, {"title": "功耗", "unit": "W", "max_value": 200, "thickness": 18, "fg_color": "#ffaa00"}, {"title": "内存使用", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#55aaff"}, {"title": "网络带宽", "unit": "Mbps", "max_value": 1000, "thickness": 18, "fg_color": "#aa55ff"}, {"title": "MLU利用率", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#00cc99"}, {"title": "CPU利用率", "unit": "%", "max_value": 100, "thickness": 18, "fg_color": "#ff55ff"} ] # 使用网格布局排列进度条 (保持不变) self.progress_bars = [] for i, config in enumerate(monitor_config): frame = tb.Frame(progress_container) frame.grid(row=i//3, column=i%3, padx=15, pady=15, sticky="nsew") # 创建增强型进度条 progress_bar = EnhancedCircularProgressBar( frame, size=220, thickness=config["thickness"], title=config["title"], unit=config["unit"], max_value=config["max_value"], fg_color=config["fg_color"], glow_effect=True ) self.progress_bars.append(progress_bar) progress_bar.canvas.pack(fill=tk.BOTH, expand=True) # 设置网格列权重 (保持不变) for i in range(3): progress_container.columnconfigure(i, weight=1) for i in range(2): progress_container.rowconfigure(i, weight=1) # ========== 状态栏 ========== self.status = tb.Label( self.root, text="系统准备就绪 | 当前设备: 设备A", bootstyle=(SECONDARY, INVERSE), anchor=tk.CENTER ) self.status.pack(side=tk.BOTTOM, fill=tk.X) # 监控控制变量 self.monitoring_active = False self.monitoring_thread = None # 启动初始监控 self.start_monitoring() # 设置定时器处理数据队列 self.root.after(100, self.process_updates) # 窗口关闭事件处理 self.root.protocol("WM_DELETE_WINDOW", self.on_close) self.root.mainloop() def start_monitoring(self): """启动资源监控""" if self.monitoring_active: return self.status.config(text="启动系统资源监控...") self.monitoring_active = True # 使用线程运行监控,避免阻塞UI self.monitoring_thread = threading.Thread(target=self.monitor_resources, daemon=True) self.monitoring_thread.start() def stop_monitoring(self): """停止资源监控""" self.monitoring_active = False self.status.config(text="监控已暂停") def reset_all(self): """重置所有监控指标""" for bar in self.progress_bars: bar.reset() self.status.config(text="所有监控指标已重置") def receive_real_data(self): """接收并解析真实硬件数据""" try: data, _ = self.udp_socket.recvfrom(4096) data_str = data.decode('utf-8') try: # 解析JSON数据 data_dict = json.loads(data_str) # 更新real_data self.real_data["cpu_temp"] = data_dict.get("cpu_temp", 0.0) self.real_data["power"] = data_dict.get("power", 0.0) # 计算内存使用百分比 mem_used = data_dict.get("memory_used", 0) mem_total = data_dict.get("memory_total", 1) # 避免除零错误 if mem_total > 0: self.real_data["memory"] = (mem_used / mem_total) * 100 self.real_data["bandwidth"] = data_dict.get("bandwidth", 0.0) self.real_data["mlu_usage"] = data_dict.get("mlu_usage", 0.0) self.real_data["cpu_usage"] = data_dict.get("cpu_usage", 0.0) except json.JSONDecodeError: # 兼容旧版文本格式 self._legacy_parse(data_str) except socket.timeout: pass # 没有数据是正常的 except Exception as e: print(f"接收数据错误: {e}") def _legacy_parse(self, info_str): """兼容旧版文本格式解析""" try: # 解析CPU温度 temp_match = re.search(r"Board\s+:\s+(\d+\.?\d*)\s*C", info_str) if temp_match: self.real_data["cpu_temp"] = float(temp_match.group(1)) # 解析功耗 power_match = re.search(r"Usage\s+:\s+(\d+\.?\d*)\s*W", info_str) if power_match: self.real_data["power"] = float(power_match.group(1)) # 解析内存使用率 mem_match = re.search(r"Used\s+:\s+(\d+)\s*MiB.*?Total\s+:\s+(\d+)\s*MiB", info_str, re.DOTALL) if mem_match: used = float(mem_match.group(1)) total = float(mem_match.group(2)) if total > 0: self.real_data["memory"] = (used / total) * 100 # 解析带宽 bw_match = re.search(r"Bandwidth\s+:\s+([\d.]+)\s*GB/s", info_str) if bw_match: self.real_data["bandwidth"] = float(bw_match.group(1)) # 解析MLU利用率 mlu_match = re.search(r"MLU Average:\s*(\d+\.?\d*)%", info_str) if mlu_match: self.real_data["mlu_usage"] = float(mlu_match.group(1)) # 解析CPU利用率 cpu_match = re.search(r"Device CPU Chip:\s*(\d+\.?\d*)%", info_str) if cpu_match: self.real_data["cpu_usage"] = float(cpu_match.group(1)) except Exception as e: print(f"旧版解析错误: {e}") def monitor_resources(self): """监控系统资源""" while self.monitoring_active: # 接收并解析真实数据 self.receive_real_data() # 使用真实数据或模拟数据 cpu_temp = self.real_data["cpu_temp"] or self.get_cpu_temperature() power = self.real_data["power"] or self.get_power_usage() mem_usage = self.real_data["memory"] or self.get_memory_usage() # 带宽单位转换:GB/s → Mbps (1 GB/s = 8000 Mbps) bandwidth_gb = self.real_data["bandwidth"] network = bandwidth_gb * 8000 # 转换为Mbps if network <= 0: # 如果真实数据无效,使用模拟数据 network = self.get_network_usage() mlu_usage = self.real_data["mlu_usage"] or self.get_mlu_usage() cpu_usage = self.real_data["cpu_usage"] or psutil.cpu_percent() # 将数据放入队列,由主线程更新UI self.data_queue.put((cpu_temp, power, mem_usage, network, mlu_usage, cpu_usage)) time.sleep(1) def process_updates(self): """从队列中取出数据并更新UI(在主线程中调用)""" try: while not self.data_queue.empty(): data = self.data_queue.get_nowait() # 更新进度条 self.progress_bars[0].set_value(data[0]) self.progress_bars[1].set_value(data[1]) self.progress_bars[2].set_value(data[2]) self.progress_bars[3].set_value(data[3]) self.progress_bars[4].set_value(data[4]) self.progress_bars[5].set_value(data[5]) # 更新状态栏 status_text = ( f"CPU: {data[5]:.1f}% | " f"温度: {data[0]:.1f}°C | " f"内存: {data[2]:.1f}% | " f"MLU: {data[4]:.1f}%" ) self.status.config(text=status_text) except queue.Empty: pass # 每100毫秒检查一次 self.root.after(100, self.process_updates) def get_cpu_temperature(self): """获取CPU温度(模拟)""" base_temp = 40.0 fluctuation = random.uniform(-2, 8) load_factor = self.progress_bars[5].current_value / 100 * 10 return min(100, max(30, base_temp + fluctuation + load_factor)) def get_power_usage(self): """获取功耗使用(模拟)""" base_power = 80.0 fluctuation = random.uniform(-10, 15) load_factor = (self.progress_bars[5].current_value + self.progress_bars[4].current_value) / 200 * 50 return min(200, max(50, base_power + fluctuation + load_factor)) def get_memory_usage(self): """获取内存使用率""" return psutil.virtual_memory().percent def get_network_usage(self): """获取网络带宽使用(模拟)""" base_usage = 300.0 fluctuation = random.uniform(-50, 100) return min(1000, max(0, base_usage + fluctuation)) def get_mlu_usage(self): """获取MLU利用率(模拟)""" base_usage = 30.0 fluctuation = random.uniform(-5, 15) load_factor = random.uniform(0, 40) return min(100, max(0, base_usage + fluctuation + load_factor)) def change_theme(self): """更改应用主题""" theme = self.theme_var.get() tb.Style(theme=theme) self.status.config(text=f"主题已切换为: {theme.capitalize()}") def on_close(self): """窗口关闭时清理资源""" self.monitoring_active = False if self.monitoring_thread and self.monitoring_thread.is_alive(): self.monitoring_thread.join(timeout=2.0) try: if self.monitor_service: self.monitor_service.stop_service() self.udp_socket.close() except Exception as e: print(f"关闭资源时出错: {e}") self.root.destroy() if __name__ == "__main__": # 设置无缓冲输出 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', line_buffering=True) # 启动GUI应用 SystemMonitorApp() 现在这段程序需要分为两部分,第一部分是服务端MLU220运行Server文件然后返回文本数据,第二部分是客户端主机接收服务端MLU220的文本数据并提取这些文本数据显示在主机写好的UI界面中,应该怎么拆开,使用Socket通讯。
最新发布
06-21
import fitz # PyMuPDF import os import re from tkinter import filedialog, messagebox, Tk, Toplevel, Label, IntVar from tkinter.ttk import Progressbar import traceback from win32com import client import pythoncom def update_status(completed_pdfs): """ 用于更新文件处理的状态,保存到 status.txt 文件中。 """ with open("status.txt", "w") as status_file: status_file.write(f"累计完成文件: {completed_pdfs}") def clean_filename(filename): """ 仅保留文件名中的汉字、字母、数字和“-”的部分,并替换下划线为“-”。 """ return re.sub(r"[^\u4e00-\u9fa5a-zA-Z0-9\-]", "", filename).replace("_", "-") def save_pdf_page_as_image(pdf_document, pdf_name, page_num, output_folder, dpi_value=144): """ 将 PDF 单页保存为清晰度更高的 PNG 文件。 """ try: os.makedirs(output_folder, exist_ok=True) output_file = os.path.join(output_folder, f"{pdf_name}-Page-{page_num + 1}.png") if os.path.exists(output_file): return page = pdf_document.load_page(page_num) zoom_ratio = dpi_value / 72.0 pix = page.get_pixmap(matrix=fitz.Matrix(zoom_ratio, zoom_ratio)) pix.save(output_file) except Exception as e: print(f"Error saving page {page_num + 1} as image of {pdf_name}: {e}") traceback.print_exc() def split_pdf_pages(pdf_document, pdf_name, total_pages, output_base_folder, progress_var, progress_window): """ 将 PDF 按页切分并保存到单独的图片文件中。 """ # 为每个 PDF 创建对应的输出文件夹 pdf_folder = os.path.join(output_base_folder, pdf_name) os.makedirs(pdf_folder, exist_ok=True) for page_num in range(total_pages): save_pdf_page_as_image(pdf_document, pdf_name, page_num, pdf_folder) # 更新进度条 progress_var.set(progress_var.get() + 1) progress_window.update() def process_pdf(pdf_path, output_folder, progress_var, progress_label, progress_window): """ 处理 PDF 文件,将每页保存为单独的 PNG 文件。 """ try: original_pdf_name = os.path.splitext(os.path.basename(pdf_path))[0] pdf_name = clean_filename(original_pdf_name) # 清洗 PDF 文件名 # 打开 PDF 文件并获取页数 pdf_document = fitz.open(pdf_path) total_pages = len(pdf_document) # 更新当前处理文件的状态 progress_label.config(text=f"正在处理文件:{pdf_name} ({total_pages} 页)") progress_window.update() # 按页切分并保存 split_pdf_pages(pdf_document, pdf_name, total_pages, output_folder, progress_var, progress_window) pdf_document.close() # 关闭 PDF 文档 return True except Exception as e: print(f"Failed to process PDF {pdf_path}: {e}") traceback.print_exc() return False def convert_word_to_pdf(doc_path): """ 将 Word 文档转换为 PDF,并返回新生成的 PDF 路径。 """ try: pythoncom.CoInitialize() # 初始化 COM word = client.DispatchEx("Word.Application") doc = word.Documents.Open(doc_path) pdf_path = os.path.splitext(doc_path)[0] + ".pdf" doc.SaveAs(pdf_path, FileFormat=17) doc.Close() word.Quit() return pdf_path except Exception as e: print(f"Failed to convert {doc_path} to PDF: {e}") traceback.print_exc() return None def process_files_in_folder(input_folder, output_folder, progress_window, progress_label, progress_bar, progress_var): """ 遍历输入文件夹中的所有 PDF 和 Word 文件并处理。 """ file_list = [] total_pages = 0 for root, _, files in os.walk(input_folder): for file in files: file_path = os.path.join(root, file) if file.lower().endswith('.pdf'): file_list.append(file_path) total_pages += fitz.open(file_path).page_count elif file.lower().endswith('.doc') or file.lower().endswith('.docx'): pdf_path = convert_word_to_pdf(file_path) if pdf_path: file_list.append(pdf_path) total_pages += fitz.open(pdf_path).page_count progress_bar.config(maximum=total_pages) completed_pdfs = 0 for file_path in file_list: if process_pdf(file_path, output_folder, progress_var, progress_label, progress_window): completed_pdfs += 1 update_status(completed_pdfs) progress_window.destroy() # 关闭进度窗口 messagebox.showinfo("完成", f"共处理完成 {completed_pdfs} 个 PDF 文件") # 显示完成信息 def main(): """ 主程序入口,处理输入和输出文件夹的选择,并调用文件处理逻辑。 """ root = Tk() root.withdraw() # 隐藏主窗口 # 选择输入和输出目录 input_folder = filedialog.askdirectory(title="选择包含PDF和Word文件的文件夹") if not input_folder: print("未选择输入文件夹,程序终止") return output_folder = filedialog.askdirectory(title="选择输出文件夹") if not output_folder: print("未选择输出文件夹,程序终止") return # 创建一个进度条显示的窗口 progress_window = Toplevel() progress_window.title("处理进度") progress_window.geometry("400x150") progress_label = Label(progress_window, text="正在初始化...", anchor='w') progress_label.pack(fill='x', padx=10, pady=5) progress_var = IntVar() progress_bar = Progressbar(progress_window, orient="horizontal", length=300, mode="determinate", variable=progress_var) progress_bar.pack(padx=10, pady=5) # 开始文件处理,显示进度 process_files_in_folder(input_folder, output_folder, progress_window, progress_label, progress_bar, progress_var) root.mainloop() if __name__ == "__main__": main() 修改一下代码,使该代码可以在linux环境下运行,且运行效果不变
05-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值