如何在Tkinter错误日志工具中实现图片粘贴保存功能
实现Tkinter错误日志工具的图片粘贴与保存功能
现有场景与需求
我有一个用于错误日志记录的Python脚本,目前支持用户输入错误文本和类别,并保存到CSV文件。但工作站用户没有本地文件保存权限,只能通过Windows截图工具或PrintScreen快捷键复制图片,需要在Tkinter窗口中添加图片粘贴功能并完成图片保存。
现有代码
import csv import datetime import tkinter as tk from tkinter import messagebox import os import configparser config = configparser.ConfigParser() config.read("C:/Users/Public/Documents/Intel/Strata/CfgFiles/Stationdata.ini") #Locationdata for PD dataframe. for key, value in config["StationData"].items(): print(value) config.read("C:/Users/Public/Documents/Intel/Strata/CfgFiles/Appinfo.ini") for key, version in config["About"].items(): print(version) def log_error(category, error): with open("//datagrovera.ra.intel.com/DeviceLabUser/Shared/Device lab Error Logger/error_log.txt", 'a', newline='')as error_log: writer = csv.writer(error_log, delimiter=',') writer.writerow([datetime.datetime.now(), error, category, value, version]) def main(): root = tk.Tk() root.geometry('300x200') root.title(value) category_var = tk.StringVar(root) category_var.set('Strata') category_dropdown = tk.OptionMenu(root, category_var, 'Strata', 'Prober', 'General') category_dropdown.pack(pady=10) error_label = tk.Label(root, text='Error:') error_label.pack() error_entry = tk.Entry(root) error_entry.pack(expand = True, fill = tk.X) def log_error_callback(): category = category_var.get() error = error_entry.get() if not error: messagebox.showerror('Error', 'Please enter an error message') return log_error(category, error) messagebox.showinfo('Success', f'Error logged for {category} category') log_button = tk.Button(root, text='Log Error', command=log_error_callback) log_button.pack() root.mainloop() if __name__ == '__main__': main()
解决方案
针对Windows平台的图片粘贴需求,可借助pywin32读取剪贴板图片,用Pillow处理图片格式,最后将图片保存到用户有权限访问的共享目录,同时把图片路径关联到错误日志中。
步骤1:安装依赖包
需要安装两个核心库:
pip install pywin32 pillow
步骤2:修改后的完整代码
import csv import datetime import tkinter as tk from tkinter import messagebox, Label import os import configparser import win32clipboard from PIL import Image, ImageTk import uuid # 读取配置文件 config = configparser.ConfigParser() config.read("C:/Users/Public/Documents/Intel/Strata/CfgFiles/Stationdata.ini") value = next(iter(config["StationData"].values())) # 获取StationData第一个值 config.read("C:/Users/Public/Documents/Intel/Strata/CfgFiles/Appinfo.ini") version = next(iter(config["About"].values())) # 获取About版本值 # 共享目录配置(确保用户有写入权限) SHARED_DIR = "//datagrovera.ra.intel.com/DeviceLabUser/Shared/Device lab Error Logger" IMAGE_SUB_DIR = os.path.join(SHARED_DIR, "error_screenshots") os.makedirs(IMAGE_SUB_DIR, exist_ok=True) # 自动创建截图子目录 current_img_path = None # 存储当前粘贴的图片路径 def save_clipboard_image(): """读取剪贴板图片并保存到共享目录""" try: win32clipboard.OpenClipboard() # 检查剪贴板是否包含图片数据 if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_DIB): data = win32clipboard.GetClipboardData(win32clipboard.CF_DIB) img = Image.frombytes('RGB', (data.width, data.height), data.bits) # 生成唯一文件名(时间戳+短UUID) img_filename = f"{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}.png" img_path = os.path.join(IMAGE_SUB_DIR, img_filename) img.save(img_path, format='PNG') return img_path else: messagebox.showwarning("提示", "剪贴板中没有图片内容") return None except Exception as e: messagebox.showerror("错误", f"保存图片失败:{str(e)}") return None finally: win32clipboard.CloseClipboard() def log_error(category, error, img_path=None): """记录错误日志,支持关联图片路径""" log_row = [datetime.datetime.now(), error, category, value, version] if img_path: log_row.append(img_path) with open(os.path.join(SHARED_DIR, 'error_log.txt'), 'a', newline='', encoding='utf-8') as error_log: writer = csv.writer(error_log, delimiter=',') writer.writerow(log_row) def main(): global current_img_path root = tk.Tk() root.geometry('400x350') root.title(value) # 错误类别选择 category_var = tk.StringVar(root) category_var.set('Strata') category_dropdown = tk.OptionMenu(root, category_var, 'Strata', 'Prober', 'General') category_dropdown.pack(pady=10) # 错误信息输入框 error_label = tk.Label(root, text='错误描述:') error_label.pack() error_entry = tk.Entry(root) error_entry.pack(expand=True, fill=tk.X, padx=10, pady=5) # 图片预览区域 preview_label = Label(root, text="截图预览:") preview_label.pack(pady=5) img_preview = Label(root, borderwidth=1, relief='solid') img_preview.pack(pady=5) def paste_image_callback(): """粘贴剪贴板图片并显示预览""" global current_img_path img_path = save_clipboard_image() if img_path: current_img_path = img_path # 生成缩小的预览图 preview_img = Image.open(img_path) preview_img.thumbnail((250, 180)) tk_img = ImageTk.PhotoImage(preview_img) img_preview.config(image=tk_img) img_preview.image = tk_img # 保留引用避免图片被回收 # 粘贴截图按钮 paste_btn = tk.Button(root, text='粘贴截图', command=paste_image_callback) paste_btn.pack(pady=5) def log_error_callback(): """提交错误日志的回调""" category = category_var.get() error = error_entry.get().strip() if not error: messagebox.showerror('错误', '请输入错误描述') return log_error(category, error, current_img_path) messagebox.showinfo('成功', f'{category}类别的错误已记录') # 清空输入与预览 error_entry.delete(0, tk.END) img_preview.config(image='') global current_img_path current_img_path = None # 记录错误按钮 log_button = tk.Button(root, text='记录错误', command=log_error_callback) log_button.pack(pady=10) root.mainloop() if __name__ == '__main__': main()
核心功能说明
- 剪贴板图片读取:通过
win32clipboard访问Windows剪贴板,识别并提取图片数据 - 图片存储:将图片保存到共享目录的专属子文件夹,用时间戳+UUID生成唯一文件名避免冲突
- 日志关联:把图片路径追加到错误日志行中,实现错误文本与截图的绑定
- 预览功能:粘贴后显示缩小的截图,让用户确认粘贴内容是否正确
内容的提问来源于stack exchange,提问作者Marshmellow Physics
相关产品推荐
相关产品推荐

