Python截图轻量化工具
这是用Python做到截图工具,不过由于使用了ctypes调用了Windows的API, 同时访问了Windows中"C:/Windows/Cursors/"中的.cur光标样式文件, 这个工具只适用于Windows环境;
如果要提升其跨平台性的话,需要考虑替换ctypes的一些专属于Windows的API以及设置不同的.cur访问方式;
该模块只使用了PIL这一个第三方库,和别的使用pygame\pyautogui等模块不同,该工具着重强调轻量化,无关或没必要使用的库尽可能不使用。
目前模块尚未完成,只包含了基本的截图时调整大小,保存,翻页查看不同截图这些简单功能;后续会继续完善,但当前模块的可用性已足够,且代码经过重构,具备一定的可读性以及可拓展性。
完整代码如下,单文件,自行安装PIL模块,在Windows环境上运行。
import ctypes
import tkinter as tk
from tkinter import messagebox, filedialog
from PIL import ImageGrab, ImageTkScaleFactor = ctypes.windll.shcore.GetScaleFactorForDevice(0)
ctypes.windll.shcore.SetProcessDpiAwareness(1)class FlatButton(tk.Label):def __init__(self, parent, command, enter_fg="#000000", click_color="#25C253", *args, **kwargs):super().__init__(parent, *args, **kwargs)self.__fg = fg = kwargs.get("fg", "#474747")self.__enter_fg = enter_fgself.__click_fg = click_colorself.command = commandself.config(cursor="hand2")self.bind("<Enter>", lambda _: self.config(fg=enter_fg))self.bind("<Leave>", lambda _: self.config(fg=fg))self.bind("<Button-1>", lambda _: self.config(fg=click_color))self.bind("<ButtonRelease-1>", self.__command)if fg == enter_fg:raise ValueError("enter_fg must be different from fg")def __command(self, event):try:if self.cget("fg") in (self.__enter_fg, self.__click_fg):self.command(event)self.config(fg=self.__fg)except tk.TclError:# Button have been destroy.passclass AdjustableRect(object):"""The judgement seq is so important that you must care about:(right, bottom), (left, top), (right, top), (left, bottom),(center_x, top), (center_x, bottom), (left, center_y, ), (right, center_y)"""ANCHOR_SIZE = 3ANCHOR_HOVER_DISTANCE = 20CURSOR_FILES_NAME = ["aero_nwse_l.cur", "aero_nesw_l.cur", "aero_ns_l.cur", "aero_ew_l.cur"]CURSOR_FILES = [f"@C:/Windows/Cursors/{cursor_file}" for cursor_file in CURSOR_FILES_NAME]CURSORS = [CURSOR_FILES[0], CURSOR_FILES[0], CURSOR_FILES[1], CURSOR_FILES[1],CURSOR_FILES[2], CURSOR_FILES[2], CURSOR_FILES[3], CURSOR_FILES[3],"fleur", "arrow"]def __init__(self, parent, screenshot):self.parent: tk.Canvas = parentself.screenshot: ScreenshotUtils = screenshotself.__rect: int = 0self.__anchors: list[int] = []self.anchor_id: int = 0def rect_coords(self) -> tuple[int, int, int, int]:try:return self.parent.coords(self.__rect)except tk.TclError:return [min(self.screenshot.start_x, self.screenshot.end_x),min(self.screenshot.start_y, self.screenshot.end_y),max(self.screenshot.start_x, self.screenshot.end_x),max(self.screenshot.start_y, self.screenshot.end_y)]def anchor_coords(self) -> tuple[int, int, int, int]:left, top, right, bottom = self.rect_coords()horizontal_middle = (left + right) // 2vertical_middle = (top + bottom) // 2return ((left, top), (horizontal_middle, top), (right, top), (right, vertical_middle),(right, bottom), (horizontal_middle, bottom), (left, bottom), (left, vertical_middle))def get_anchor(self, event) -> int:cls = self.__class__left, top, right, bottom = self.rect_coords()center_x, center_y = (left + right) // 2, (top + bottom) // 2def near(actual, target):return abs(actual - target) < cls.ANCHOR_HOVER_DISTANCE# 务必注意这个判断顺序,这与后面rect_adjust密切相关judgement_pos = ((right, bottom), (left, top), (right, top), (left, bottom),(center_x, top), (center_x, bottom), (left, center_y, ), (right, center_y))for index, pos in enumerate(judgement_pos):if near(event.x, pos[0]) and near(event.y, pos[1]):return indexif left < event.x < right and top < event.y < bottom:return 8return -1def create_anchors(self):cls = self.__class__for coord in self.anchor_coords():anchor = self.parent.create_rectangle(coord[0]-cls.ANCHOR_SIZE, coord[1]-cls.ANCHOR_SIZE,coord[0]+cls.ANCHOR_SIZE, coord[1]+cls.ANCHOR_SIZE,fill="#1AAE1A", outline="#1AAE1A")self.__anchors.append(anchor)def move_anchors(self):cls = self.__class__for anchor, coord in zip(self.__anchors, self.anchor_coords()):self.parent.coords(anchor, coord[0]-cls.ANCHOR_SIZE, coord[1]-2, coord[0]+cls.ANCHOR_SIZE, coord[1]+cls.ANCHOR_SIZE)def on_press(self, event):self.screenshot.start_x = event.xself.screenshot.start_y = event.yself.__rect= self.parent.create_rectangle(self.screenshot.start_x, self.screenshot.start_y, self.screenshot.start_x, self.screenshot.start_y, outline='#1AAE1A', width=2)self.create_anchors()def on_release(self, _):self.screenshot.start_x, self.screenshot.start_y,\self.screenshot.end_x, self.screenshot.end_y = self.rect_coords()def on_hover(self, event):self.anchor_id = self.get_anchor(event)cursor = self.CURSORS[self.anchor_id]self.parent.config(cursor=cursor)def move_rect(self, event):offset_x = event.x - self.screenshot.move_start_xoffset_y = event.y - self.screenshot.move_start_yself.screenshot.start_x += offset_xself.screenshot.start_y += offset_yself.screenshot.end_x += offset_xself.screenshot.end_y += offset_yself.screenshot.move_start_x = event.xself.screenshot.move_start_y = event.yself.parent.coords(self.__rect, self.screenshot.start_x, self.screenshot.start_y, self.screenshot.end_x, self.screenshot.end_y)self.move_anchors()def rect_adjust(self, event):if self.anchor_id == 8:return self.move_rect(event)if self.anchor_id == 0:self.screenshot.end_x, self.screenshot.end_y = event.x, event.yelif self.anchor_id == 1:self.screenshot.start_x, self.screenshot.start_y = event.x, event.yelif self.anchor_id == 2:self.screenshot.end_x, self.screenshot.start_y = event.x, event.yelif self.anchor_id == 3:self.screenshot.start_x, self.screenshot.end_y = event.x, event.yelif self.anchor_id == 4:self.screenshot.start_y = event.yelif self.anchor_id == 5:self.screenshot.end_y = event.yelif self.anchor_id == 6:self.screenshot.start_x = event.xelif self.anchor_id == 7:self.screenshot.end_x = event.xelse:returnself.parent.coords(self.__rect, self.screenshot.start_x, self.screenshot.start_y, self.screenshot.end_x, self.screenshot.end_y)self.move_anchors()class ScreenshotUtils(object):"""截图的关键是坐标;这个类管理着图片的引用和截图坐标;"""def TkS(value) -> int:return int(ScaleFactor/100*value)ZOOM: int = 4ZOOM_WIDTH: float = TkS(28.75)ZOOM_SCREEN_SIZE: int = int(ZOOM_WIDTH*ZOOM)MAGNIFIER_OFFSET: int = 36AJUST_BAR_WIDTH: int = TkS(100)# 截图相关变量def __init__(self):self.start_x = self.start_y = self.end_x = self.end_y = 0self.move_start_x = self.move_start_y = self.move_end_x = self.move_end_y = 0self.current_image = Noneself.pixel_reader = Noneself.final_images = list()# 这种是只移动但不改变大小和内容的控件,只需移动无需重绘self.screenshot_move_widget = list()# 这种是移动和改变大小的控件,需要实时重绘self.screenshot_redraw_widget = list()@staticmethoddef TkS(value) -> int:return int(ScaleFactor/100*value)@classmethoddef move_widget_coords(cls, x, y) -> list[tuple[int, int, int, int]]:# 按照主框架,水平线,垂直线的顺序返回坐标magnifier_x = x+cls.MAGNIFIER_OFFSETmagnifier_y = y+cls.MAGNIFIER_OFFSETmain_frame_coord = (magnifier_x, magnifier_y,magnifier_x+cls.ZOOM_SCREEN_SIZE,magnifier_y+cls.ZOOM_SCREEN_SIZE )horrontal_line_coord = (magnifier_x, magnifier_y+cls.ZOOM_SCREEN_SIZE // 2,magnifier_x+cls.ZOOM_SCREEN_SIZE,magnifier_y+cls.ZOOM_SCREEN_SIZE // 2 )vertical_line_coord = (magnifier_x+cls.ZOOM_SCREEN_SIZE // 2, magnifier_y,magnifier_x+cls.ZOOM_SCREEN_SIZE // 2,magnifier_y+cls.ZOOM_SCREEN_SIZE )coords = [main_frame_coord, horrontal_line_coord, vertical_line_coord]return coordsdef redraw_widget_coords(self, x, y) -> list[tuple]:# 按照"长 × 宽"、"放大镜图像"、"POS标签"、"RGB标签"的顺序返回坐标offset = self.__class__.MAGNIFIER_OFFSETwidth_height_info = (min(self.start_x, self.end_x), min(self.start_y, self.end_y) - 40)magnifier_coord = (x + offset, y + offset)pos_info = (x + offset, y + offset+self.__class__.ZOOM_SCREEN_SIZE + 10)rgb_info = (x + offset, y + offset+self.__class__.ZOOM_SCREEN_SIZE + 47)coords = [width_height_info, magnifier_coord, pos_info, rgb_info]return coordsclass MainUI(tk.Tk):def __init__(self):super().__init__()self.screenshot = ScreenshotUtils()self.set_window()self.menu_bar: tk.Frame = self.set_menubar()self.cut_btn: tk.Label = self.set_cut_btn()self.save_btn: tk.Label = self.set_save_btn()self.turn_left_btn: tk.Label = self.set_turn_left_btn()self.turn_right_btn: tk.Label = self.set_turn_right_btn()self.show_image_canvas: tk.Canvas = self.set_show_image_canvas()self.adjust_rect: AdjustableRect = Noneself.pos_label: tk.Label = Noneself.rgb_label: tk.Label = Noneself.adjust_bar: tk.Frame = Nonedef set_window(self):self.title("截图工具")self.geometry(f"{self.screenshot.TkS(240)}x{self.screenshot.TkS(30)}")def set_menubar(self) -> tk.Frame:menubar = tk.Frame(self, bg="#FFFFFF", height=30)menubar.pack(fill=tk.X)return menubardef set_cut_btn(self) -> tk.Label:btn_cut = FlatButton(self.menu_bar, self.start_capture, text="✂", bg="#FFFFFF", font=("Segoe UI Emoji", 18),)btn_cut.pack(side=tk.LEFT, padx=5)return btn_cutdef set_save_btn(self) -> tk.Label:btn_save = FlatButton(self.menu_bar, self.save_image, text="💾", bg="#FFFFFF", font=("Segoe UI Emoji", 18),)btn_save.pack(side=tk.LEFT, padx=5)return btn_savedef set_turn_left_btn(self) -> tk.Label:turn_left_btn = FlatButton(self.menu_bar, self.turn_page, text="\u25C0", bg="#FFFFFF", font=("Segoe UI Emoji", 18),)turn_left_btn.pack(side=tk.LEFT, padx=5)return turn_left_btndef set_turn_right_btn(self) -> tk.Label:turn_page_btn = FlatButton(self.menu_bar, self.turn_page, text="\u25B6", bg="#FFFFFF", font=("Segoe UI Emoji", 18),)turn_page_btn.pack(side=tk.LEFT, padx=5)return turn_page_btndef set_cancel_btn(self, parent) -> tk.Label:cancel_btn = FlatButton(parent, self.clear_capture_info, text="×", bg="#FFFFFF",enter_fg="#DB1A21",fg="#CC181F", font=("微软雅黑", 18))cancel_btn.pack(side=tk.RIGHT, padx=5)return cancel_btndef set_confirm_btn(self, parent) -> tk.Label:confirm_btn = FlatButton(parent, self.confirm_capture, fg="#23B34C", text="√",enter_fg="#27C956", bg="#FFFFFF", font=("微软雅黑", 18))return confirm_btndef set_show_image_canvas(self) -> tk.Canvas:canvas = tk.Canvas(self, bg="white")return canvasdef set_adjust_bar(self) -> tk.Frame:self.adjust_bar = tk.Frame(self.full_screenshot_canvas, bg="#FFFFFF", height=50)cancel_btn = self.set_cancel_btn(self.adjust_bar)confirm_btn = self.set_confirm_btn(self.adjust_bar)cancel_btn.pack(side=tk.RIGHT, padx=5)confirm_btn.pack(side=tk.RIGHT, padx=10)def set_magnifier_frame(self, event) -> None:initial_coord = (0, 0, 0, 0)main_frame_id = self.full_screenshot_canvas.create_rectangle(*initial_coord, outline='#1AAE1A', width=1)horrontal_line = self.full_screenshot_canvas.create_line(*initial_coord, fill="#1AAE1A", width=2)vertical_line = self.full_screenshot_canvas.create_line(*initial_coord, fill="#1AAE1A", width=2)self.screenshot.screenshot_move_widget = [main_frame_id, horrontal_line, vertical_line]event.x = event.x + event.widget.winfo_rootx()event.y = event.y + event.widget.winfo_rooty()self.update_magnifier(event)def set_full_screenshot_canvas(self, parent) -> tk.Canvas:img = ImageGrab.grab()self.screenshot.current_image = imgself.screenshot.pixel_reader = img.convert("RGB")photo = ImageTk.PhotoImage(img)full_screenshot_canvas = tk.Canvas(parent, bg="white")full_screenshot_canvas.create_image(0, 0, anchor=tk.NW, image=photo)full_screenshot_canvas.image = photofull_screenshot_canvas.pack(fill=tk.BOTH, expand=True)return full_screenshot_canvasdef set_pos_rgb_label(self, parent) -> tk.Label:label = tk.Label(parent, bg="#000000", font=("微软雅黑", 8), fg="#ffffff")return labelclass ScreenshotTool(MainUI):def __init__(self):super().__init__()self.page_index = 0def start_capture(self, event):self.attributes('-alpha', 0)self.update()self.capture_win = tk.Toplevel()self.capture_win.geometry(f"{self.winfo_screenwidth()}x{self.winfo_screenheight()}+0+0")self.capture_win.overrideredirect(True)self.full_screenshot_canvas = self.set_full_screenshot_canvas(self.capture_win)self.pos_label = self.set_pos_rgb_label(self.full_screenshot_canvas)self.rgb_label = self.set_pos_rgb_label(self.full_screenshot_canvas)self.adjust_rect = AdjustableRect(self.full_screenshot_canvas, self.screenshot)self.set_magnifier_frame(event)self.set_adjust_bar()self.full_screenshot_canvas.bind("<Button-1>", self.on_press)self.full_screenshot_canvas.bind("<Motion>", self.update_magnifier)self.full_screenshot_canvas.bind("<ButtonRelease-1>", self.on_release)def on_press(self, event):self.adjust_rect.on_press(event)self.full_screenshot_canvas.unbind("<Motion>")self.full_screenshot_canvas.bind("<Motion>", self.on_drag)def on_drag(self, event):self.adjust_rect.rect_adjust(event)self.update_magnifier(event)def on_release(self, event, resize=True):self.unbind_all()self.adjust_rect.on_release(event)self.full_screenshot_canvas.config(cursor=self.adjust_rect.CURSOR_FILES[0])self.full_screenshot_canvas.bind("<Button-1>", self.start_move)self.full_screenshot_canvas.bind("<Motion>", self.adjust_rect.on_hover)self.adjust_bar.place(x=self.screenshot.end_x - 300, y=self.screenshot.end_y + 10, width=300)if resize:self.screenshot.end_x, self.screenshot.end_y = event.x, event.ydef unbind_all(self):events = ("<Button-1>", "<Motion>", "<ButtonRelease-1>")for event in events:self.full_screenshot_canvas.unbind(event)def update_magnifier(self, event):x, y = event.x, event.ysize = ScreenshotUtils.ZOOM_WIDTHimg = self.screenshot.current_image.crop((x - size//2, y - size//2, x + size//2, y + size//2))img = img.resize((ScreenshotUtils.ZOOM_SCREEN_SIZE, ScreenshotUtils.ZOOM_SCREEN_SIZE))photo = ImageTk.PhotoImage(img)self.full_screenshot_canvas.image2 = photow, h = abs(self.screenshot.end_x - self.screenshot.start_x), abs(self.screenshot.end_y - self.screenshot.start_y)for redraw_widget in self.screenshot.screenshot_redraw_widget:self.full_screenshot_canvas.delete(redraw_widget)self.screenshot.screenshot_redraw_widget.clear()redraw_widget_coords = self.screenshot.redraw_widget_coords(x, y)width_height_info, magnifier_coord, pos_info, rgb_info = redraw_widget_coordswh_info_widget = self.full_screenshot_canvas.create_text(*width_height_info, anchor=tk.NW, fill="white", text=f"{w} × {h}")zoom_img = self.full_screenshot_canvas.create_image(*magnifier_coord, anchor=tk.NW, image=photo)self.pos_label.config(text=f"POS: ({x}, {y})")self.rgb_label.config(text=f"RGB: {self.screenshot.pixel_reader.getpixel((x, y))}")self.pos_label.place(x=pos_info[0], y=pos_info[1])self.rgb_label.place(x=rgb_info[0], y=rgb_info[1])self.screenshot.screenshot_redraw_widget = [wh_info_widget, zoom_img]self.update_magnifier_frame(x, y)def update_magnifier_frame(self, x: int, y: int) -> None:coords = self.screenshot.move_widget_coords(x, y)for widget, coord in zip(self.screenshot.screenshot_move_widget, coords):self.full_screenshot_canvas.coords(widget, *coord)self.full_screenshot_canvas.tag_raise(widget)def start_move(self, event):self.screenshot.move_start_x = event.xself.screenshot.move_start_y = event.yself.adjust_bar.place_forget()self.pos_label.place_forget()self.rgb_label.place_forget()for widget in self.screenshot.screenshot_redraw_widget:self.full_screenshot_canvas.delete(widget)for widget in self.screenshot.screenshot_move_widget:self.full_screenshot_canvas.tag_lower(widget)self.full_screenshot_canvas.bind("<B1-Motion>", self.adjust_rect.rect_adjust)self.full_screenshot_canvas.bind("<ButtonRelease-1>", lambda e: self.on_release(e, False))def clear_capture_info(self, _):self.capture_win.destroy()self.full_screenshot_canvas.destroy()self.attributes('-alpha', 1)self.screenshot.screenshot_move_widget.clear()def confirm_capture(self, event):self.clear_capture_info(event)x1, y1, x2, y2 = self.adjust_rect.rect_coords()image = self.screenshot.current_image.crop((x1, y1, x2, y2))result = self.show_image(image)self.screenshot.final_images.append(result)self.page_index = len(self.screenshot.final_images) - 1self.attributes('-topmost', 1)def show_image(self, image):self.geometry(f"{max(image.width, ScreenshotUtils.TkS(240))}x{image.height+self.menu_bar.winfo_height()}")photo = ImageTk.PhotoImage(image)self.show_image_canvas.config(width=image.width, height=image.height)self.show_image_canvas.delete("all")self.show_image_canvas.create_image(0, 0, anchor=tk.NW, image=photo)self.show_image_canvas.image = photoself.show_image_canvas.pack()return imagedef save_image(self, _):try:image = self.screenshot.final_images[self.page_index]filename = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png"), ("JPEG files", "*.jpg")],initialfile=f"{image.width}x{image.height}.png")if not filename:returnimage.save(filename)except IndexError:messagebox.showerror("保存失败", "未检测到截取图像")def turn_page(self, event):if len(self.screenshot.final_images) == 0:return messagebox.showinfo("提示", "暂无图片可切换!")if event.widget == self.turn_left_btn:if self.page_index == 0:return messagebox.showinfo("提示", "已经是第一张图片!")self.page_index -= 1else:if self.page_index == len(self.screenshot.final_images) - 1:return messagebox.showinfo("提示", "已经是最后一张图片!")self.page_index += 1self.show_image(self.screenshot.final_images[self.page_index])if __name__ == "__main__":app = ScreenshotTool()app.mainloop()
相关文章:
Python截图轻量化工具
这是用Python做到截图工具,不过由于使用了ctypes调用了Windows的API, 同时访问了Windows中"C:/Windows/Cursors/"中的.cur光标样式文件, 这个工具只适用于Windows环境; 如果要提升其跨平台性的话,需要考虑替换ctypes的一些专属于W…...
Python----Python高级(并发编程:协程Coroutines,事件循环,Task对象,协程间通信,协程同步,将协程分布到线程池/进程池中)
一、协程 1.1、协程 协程,Coroutines,也叫作纤程(Fiber) 协程,全称是“协同程序”,用来实现任务协作。是一种在线程中,比线程更加轻量级的存在,由程序员自己写程序来管理。 当出现IO阻塞时,…...
DeepSeek使用技巧大全(含本地部署教程)
在人工智能技术日新月异的今天,DeepSeek 作为一款极具创新性和实用性的 AI,在众多同类产品中崭露头角,凭借其卓越的性能和丰富的功能,吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能,它基于先进…...
.NET Core 8 Blazor 和 Vue 3 技术构建网
以下是一个可行的解决方案,能够满足使用 .NET Core 8 Blazor 和 Vue 3 技术构建网站,并且将前后端代码放在一个站点中,实现一次发布部署的目标。 解决方案概述 技术栈选择: 后端:.NET Core 8 Blazor Server 或 Blazor …...
ElasticSearch集群因索引关闭重打开导致飘红问题排查
背景 某组件向 ElasticSearch 写入数据,从最近某一天开始写入速度变慢,数据一直有积压。推测是 ElasticSearch 集群压力导致的,查看 ElasticSearch 集群状态,发现集群确实处于 red 状态。 本文记录 ElasticSearch 集群因索引关闭…...
计算机毕业设计Tensorflow+LSTM空气质量监测及预测系统 天气预测系统 Spark Hadoop 深度学习 机器学习 人工智能
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
手搓基于CNN的Chest X-ray图像分类
数据集Chest X-ray PD Dataset 数据集介绍 - 知乎https://zhuanlan.zhihu.com/p/661311561 CPU版本 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms, models import …...
使用java代码操作rabbitMQ收发消息
SpringAMQP 将来我们开发业务功能的时候,肯定不会在控制台收发消息,而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也…...
【数据结构】(7) 栈和队列
一、栈 Stack 1、什么是栈 栈是一种特殊的线性表,它只能在固定的一端(栈顶)进行出栈、压栈操作,具有后进先出的特点。 2、栈概念的例题 答案为 C,以C为例进行讲解: 第一个出栈的是3,那么 1、…...
【Pytorch实战教程】让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南
文章目录 让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南一、为什么需要数据管理组件?二、Dataset:数据集的编程接口2.1 自定义Dataset三要素2.2 实战案例:图像分类数据集三、Dataloader:高效数据流水线3.1 核心参数解析3.2 数据流可视化3.3 多卡训练支持四、综合…...
Python的秘密基地--[章节13] Python 数据分析与可视化
第13章:Python 数据分析与可视化 在大数据时代,数据分析与可视化是至关重要的技能。Python 提供了多个强大的库,如 NumPy、Pandas、Matplotlib 和 Seaborn,用于数据处理、分析和可视化。本章将介绍如何使用 Python 进行数据分析&…...
Python 入门:文件操作、读写、管理
目录 1. 引言 2. 文件基础操作 2.1 打开文件(open()) 2.2 读取文件内容 2.3 写入文件 3. 处理 CSV 文件 3.1 读取 CSV 文件 3.2 写入 CSV 文件 4. 处理 JSON 文件 4.1 读取 JSON 文件 4.2 写入 JSON 文件 5. 文件管理操作 5.1 删除文件 5.…...
Composo:企业级AI应用的质量守门员
在当今快速发展的科技世界中,人工智能(AI)的应用已渗透到各行各业。然而,随着AI技术的普及,如何确保其可靠性和一致性成为了企业面临的一大挑战。Composo作为一家致力于为企业提供精准AI评估服务的初创公司,通过无代码和API双模式,帮助企业监测大型语言模型(LLM)驱动的…...
crictl和ctr命令详解
一,crictl crictl 是 CRI 兼容的容器运行时命令行接口。 你可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序。 crictl 和它的源代码在 cri-tools 代码库。 1,安装 需要下载与kubernetes相对应的版本,我的k8s版本是1.30的…...
Python数据分析案例71——基于十种模型的信用违约预测实战
背景 好久没写这种基础的做机器学习流程了,最近过完年感觉自己代码忘了好多.....复习一下。 本次带来的是信贷违约的预测,即根据这个人的特征(年龄收入什么的),预测他是不是会违约,会违约就拒绝贷款&…...
Lesson 131 Don‘t be so sure
Lesson 131 Don’t be so sure 词汇 Egypt n. 埃及 相关:Egyptian n. 埃及人,埃及的 camel n. 骆驼 Mummy n. 木乃伊 Pyramid n. 金字塔 Pharaoh n. 法老 例句:你去过埃及吗? Have you been to E…...
python康威生命游戏的图形化界面实现
康威生命游戏(Conway’s Game of Life)是由英国数学家约翰何顿康威(John Horton Conway)在1970年发明的一款零玩家的细胞自动机模拟游戏。尽管它的名字中有“游戏”,但实际上它并不需要玩家参与操作,而是通…...
区块链技术:Facebook 重塑社交媒体信任的新篇章
在这个信息爆炸的时代,社交媒体已经成为我们生活中不可或缺的一部分。然而,随着社交平台的快速发展,隐私泄露、数据滥用和虚假信息等问题也日益凸显。这些问题的核心在于传统社交媒体依赖于中心化服务器存储和管理用户数据,这种模…...
【自学笔记】文言一心的基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 文心一言知识点总览一、文心一言简介二、文心一言的核心功能三、文心一言的技术特点四、文心一言的应用场景五、文心一言的使用技巧六、文心一言的未来发展 总结 文…...
UE求职Demo开发日志#25 试试网络同步和尝试打包
1 改了一些时序上的bug,成功运行了多端 (UE一些网络相关的功能都弄好了,只需要标记哪个变量或Actor需要复制) 2 以前遗留的bug太多了,改到晚上才打包好一个能跑的版本,而且有的特效还不显示(悲…...
2021 年 9 月青少年软编等考 C 语言五级真题解析
目录 T1. 问题求解思路分析T2. 抓牛思路分析T3. 交易市场思路分析T4. 泳池思路分析T1. 问题求解 给定一个正整数 N N N,求最小的 M M M 满足比 N N N 大且 M M M 与 N N N 的二进制表示中有相同数目的 1 1 1。 举个例子,假如给定 N N N 为 78 78 78,二进制表示为 …...
Win10环境使用ChatBox集成Deep Seek解锁更多玩法
Win10环境使用ChatBox集成Deep Seek解锁更多玩法 前言 之前部署了14b的Deep Seek小模型,已经验证了命令行及接口方式的可行性。但是纯命令行或者PostMan方式调用接口显然不是那么友好: https://lizhiyong.blog.csdn.net/article/details/145505686 纯…...
第 26 场 蓝桥入门赛
2.对联【算法赛】 - 蓝桥云课 问题描述 大年三十,小蓝和爷爷一起贴对联。爷爷拿出了两副对联,每副对联都由 N 个“福”字组成,每个“福”字要么是正的(用 1 表示),要么是倒的(用 0 表示&#…...
CodeGPT + IDEA + DeepSeek,在IDEA中引入DeepSeek实现AI智能开发
CodeGPT IDEA DeepSeek,在IDEA中引入DeepSeek 版本说明 建议和我使用相同版本,实测2022版IDEA无法获取到CodeGPT最新版插件。(在IDEA自带插件市场中搜不到,可以去官网搜索最新版本) ToolsVersionIntelliJ IDEA202…...
【2025年更新】1000个大数据/人工智能毕设选题推荐
文章目录 前言大数据/人工智能毕设选题:后记 前言 正值毕业季我看到很多同学都在为自己的毕业设计发愁 Maynor在网上搜集了1000个大数据的毕设选题,希望对大家有帮助~ 适合大数据毕业设计的项目,完全可以作为本科生当前较新的毕…...
什么是中间件中间件有哪些
什么是中间件? 中间件(Middleware)是指在客户端和服务器之间的一层软件组件,用于处理请求和响应的过程。 中间件是指介于两个不同系统之间的软件组件,它可以在两个系统之间传递、处理、转换数据,以达到协…...
使用docker搭建FastDFS文件服务
1.拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/qiluo-images/fastdfs:latest2.使用docker镜像构建tracker容器(跟踪服务器,起到调度的作用) docker run -dti --networkhost --name tracker -v /data/fdfs/tracker:/var/fdfs -…...
使用OpenGL自己定义一个button,响应鼠标消息:掠过、点击、拖动
button需要有一个外观 外观 大小跟随窗口改变,采用纯色背景、纯色文字 文字 大小跟随窗口改变 button需要获得鼠标消息 掠过 鼠标掠过时 button 出现阴影,鼠标掠过后 button 阴影消失 点击 点击后进入相应事件 拖动 改变图标所在位置 需要在g…...
天津三石峰科技——汽车生产厂的设备振动检测项目案例
汽车产线有很多传动设备需要长期在线运行,会出现老化、疲劳、磨损等 问题,为了避免意外停机造成损失,需要加装一些健康监测设备,监测设备运 行状态。天津三石峰科技采用 12 通道振动信号采集卡(下图 1)对…...
Linux之文件IO前世今生
在 Linux之文件系统前世今生(一) VFS中,我们提到了文件的读写,并给出了简要的读写示意图,本文将分析文件I/O的细节。 一、Buffered I/O(缓存I/O)& Directed I/O(直接I/O&#…...
