news 2026/9/14 4:33:18

基于Python+tkinter+MySQL的图书管理系统全流程实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Python+tkinter+MySQL的图书管理系统全流程实战解析

简介:面向计算机相关专业毕业设计、课程设计及大作业场景,这是一套基于Python+tkinter+MySQL的图书管理系统完整项目。项目采用Python编写核心逻辑,借助tkinter构建图形操作界面,通过MySQL完成图书数据的持久化存储,覆盖用户登录、图书添加、查询、删除、修改以及库存管理等典型功能模块。代码中包含完善的异常处理与错误提示,数据库表结构设计也给出了合理方案,适合希望提升GUI编程能力与数据库开发水平的学生借鉴。压缩包内共4个文件,主要包含Python源码、PPT演示文稿、PDF项目说明文档和README说明文件,整体大小约31.62MB。PPT可用于答辩展示,源码可直接运行或在其基础上二次开发,PDF文档有助于快速梳理系统架构与实现细节。目前已有272人学习下载,能够为课程设计或毕业设计提供完整参考,帮助读者理解桌面应用从界面到数据库的整套实现思路。

1. 基于Python+tkinter+MySQL的图书管理系统要解决什么问题

很多人觉得tkinter做GUI显得过时,但放在毕业设计或课程设计里,它反而是最稳妥的选择:不需要额外安装PyQt这类第三方库,python安装教程里的标准环境就自带tkinter,用PyInstaller一打包就能跨机器运行;底层接MySQL,则能把数据管理从简单的文件读写提升到真正的数据库层面,答辩时讲索引、事务、并发都有可聊的料。

这个项目的本质,是把图书的借、还、查、藏这些业务动作,通过GUI事件驱动和SQL语句串联成一个完整闭环。开发时间往往不是花在界面拖拽上,而是花在理解数据如何流转、异常如何回滚、多记录如何分页这些“看不见”的环节上。

如果你正在做毕设或课设,或者想补一个管理类项目的开发经验,这篇文章从建库建表讲到界面交互,再讲到打包发布,把容易踩的坑和需要调的参数一次性写清楚。

2. 从表结构到连接池:图书管理系统的三层设计

2.1 为什么是tkinter + MySQL而不是PyQt + SQLite

在写任何代码之前,先解决选型问题。我见过不少同学优先选PyQt,理由是控件更现代,还有Qt Designer能拖拽界面。但PyQt5的打包体积动辄上百MB,GPL授权在答辩时也容易被老师追问。tkinter是Python标准库的一部分,装好Python就有,不需要额外pip install,这对课设这种“机房环境随时可能被还原”的场景非常关键。

数据库用MySQL而不是SQLite,是因为毕设要求里往往写着“数据库系统”几个字。SQLite只是一个嵌入式文件,没法讲事务日志、隔离级别;而mysql安装配置教程几乎是后台开发者的必修课,老师默认你会配。更重要的是,MySQL支持多用户连接、行级锁和自定义索引,后期做并发模拟时能拿出真实数据说话。

组合学习成本打包体积答辩可讲内容
tkinter + MySQL低(标准库)25MB左右GUI事件驱动、SQL优化、事务、连接池
PyQt + SQLite80MB+信号槽、QSS、文件型数据库原理
Web端 + MySQL依赖服务器HTTP协议、并发请求、前后端分离

如果只做演示和答辩,tkinter + MySQL是投入产出比最高的组合。下面所有表结构和代码都基于这个组合进行。

2.2 图书管理系统user、book、borrow三张核心表结构

图书管理系统无论功能怎么扩展,核心都围绕“谁能借、借了什么、什么时候还”来组织。我一般设计三张表:用户表、图书表、借阅表。这里给出精简但可扩展的建表SQL:

CREATE DATABASE IF NOT EXISTS library_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE library_db; -- 用户表:区分管理员和普通借阅者 CREATE TABLE user ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE COMMENT '登录名', password CHAR(64) NOT NULL COMMENT 'SHA256哈希后的密码,不存明文', real_name VARCHAR(50) DEFAULT NULL COMMENT '真实姓名', role ENUM('admin','reader') DEFAULT 'reader' COMMENT '角色', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 图书表:基本信息与库存状态 CREATE TABLE book ( id INT AUTO_INCREMENT PRIMARY KEY, isbn VARCHAR(20) UNIQUE COMMENT 'ISBN号', title VARCHAR(200) NOT NULL COMMENT '书名', author VARCHAR(100) DEFAULT NULL, publisher VARCHAR(100) DEFAULT NULL, category VARCHAR(50) DEFAULT NULL COMMENT '分类', total INT NOT NULL DEFAULT 1 COMMENT '总数量', available INT NOT NULL DEFAULT 1 COMMENT '可借数量', location VARCHAR(50) COMMENT '馆藏位置' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 借阅表:一条借阅记录对应一本书的借出和归还 CREATE TABLE borrow ( id INT AUTO_INCREMENT PRIMARY KEY, user_id INT NOT NULL, book_id INT NOT NULL, borrow_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, due_date DATETIME NOT NULL COMMENT '应还日期', return_date DATETIME DEFAULT NULL COMMENT '实际归还日期,NULL表示未还', status ENUM('borrowed','returned','overdue') DEFAULT 'borrowed', FOREIGN KEY (user_id) REFERENCES user(id), FOREIGN KEY (book_id) REFERENCES book(id), INDEX idx_user_borrow (user_id, status), INDEX idx_book_available (available) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

逻辑说明:available字段用来避免每次计算“总库存-借出数”,但这也意味着更新时要保证一致性,我会在借阅时用事务同时更新availableborrowstatus可以用于后期统计逾期记录,比如“有多少人借了书超过30天没还”。索引idx_book_availableidx_user_borrow对高频查询很有用,第四章会用EXPLAIN验证它们是否生效。

参数说明:CHAR(64)是为了容纳SHA256的64位十六进制哈希值;utf8mb4utf8多支持生僻字和emoji,mysql安装配置教程里也建议默认使用。ENGINE=InnoDB必须显式指定,因为只有InnoDB支持事务和外键,MyISAM在这两点上都不满足,不适合图书管理这种对一致性有要求的场景。

2.3 用PyMySQL建立连接与一个简单的连接池

Python连接MySQL最常见的库是PyMySQL,纯Python实现,不用编译,适合和tkinter一起打包。我的做法是单独建一个db.py模块管理连接,不把数据库配置散落在各界面代码里。

最基本的连接方式是这样:

import pymysql db_config = { 'host': 'localhost', 'port': 3306, 'user': 'root', 'password': '123456', 'database': 'library_db', 'charset': 'utf8mb4', 'cursorclass': pymysql.cursors.DictCursor, 'autocommit': False, # 关闭自动提交,事务由代码显式控制 } def get_connection(): return pymysql.connect(**db_config)

注意autocommit=False,这是后面处理事务的关键。如果autocommit=True,那么conn.begin()不会生效,每条SQL都会立刻提交,数据一致性就无从谈起。

连接池可以减少反复建立TCP连接的开销。tkinter是单击GUI,频繁点击按钮时,每次动态建立连接会明显卡顿。我会在db.py里用queue.Queue维护一个最小连接池:

import queue import pymysql class ConnectionPool: def __init__(self, max_conn=5): self._pool = queue.Queue(maxsize=max_conn) for _ in range(max_conn): self._pool.put(pymysql.connect(**db_config)) def acquire(self, timeout=3): conn = self._pool.get(timeout=timeout) try: # 连接可能被MySQL服务端超时断开,ping失败则重建 conn.ping(reconnect=True) except Exception: conn = pymysql.connect(**db_config) return conn def release(self, conn): self._pool.put(conn)

逻辑说明:acquire从队列取一个现成的连接,ping(reconnect=True)会在连接失效时自动重连。release把用过的连接放回队列,等待下一次复用。这里没有做线程锁,因为tkinter的主要逻辑都在主线程跑,同一时刻只有一个连接会被取出。如果你用后台线程做批量数据导入,再考虑给池子加threading.Lock

参数说明:max_conn=5对单机单应用已经够用,tkinter的事件循环决定了同一时间最多只有一个数据库操作在执行。当你的系统里同时有多个窗口查询时,5个连接也能支撑。

3. 用ttk.Treeview实现图书列表和增删改查

3.1 登录窗口:界面与数据库校验

tkinter开发遵循“构建控件 + 定义事件函数 + 启动主循环”三步。这里使用tkinter.ttk子模块,因为ttk的控件样式更接近现代系统,你搜到的“tkinter ttk”就是指这一套组件。登录窗口的思路是:用户输入用户名密码,点击登录,后台查询user表并校验SHA256哈希。

import tkinter as tk from tkinter import ttk, messagebox import hashlib from db import get_connection class LoginWindow: def __init__(self): self.win = tk.Tk() self.win.title("图书管理系统 - 登录") self.win.geometry("400x260") self.win.resizable(False, False) frame = ttk.Frame(self.win, padding=20) frame.pack(fill=tk.BOTH, expand=True) ttk.Label(frame, text="用户名").grid(row=0, column=0, pady=5, sticky=tk.E) self.username_var = tk.StringVar(value="admin") ttk.Entry(frame, textvariable=self.username_var, width=25).grid(row=0, column=1, pady=5) ttk.Label(frame, text="密码").grid(row=1, column=0, pady=5, sticky=tk.E) self.password_var = tk.StringVar() ttk.Entry(frame, textvariable=self.password_var, show="*", width=25).grid(row=1, column=1, pady=5) ttk.Button(frame, text="登录", command=self.check_login).grid(row=2, column=1, pady=20, sticky=tk.EW) def check_login(self): username = self.username_var.get().strip() password = self.password_var.get() if not username or not password: messagebox.showwarning("提示", "用户名和密码不能为空") return sql = "SELECT id, role FROM user WHERE username=%s AND password=%s" pwd_hash = hashlib.sha256(password.encode()).hexdigest() try: conn = get_connection() with conn.cursor() as cursor: cursor.execute(sql, (username, pwd_hash)) user = cursor.fetchone() conn.close() except Exception as e: messagebox.showerror("数据库错误", str(e)) return if user: messagebox.showinfo("成功", "登录成功") self.win.destroy() from main_window import MainWindow MainWindow(user) else: messagebox.showerror("失败", "用户名或密码错误") def run(self): self.win.mainloop()

逻辑说明:密码在存储前经过SHA256哈希,数据库里不会出现明文。SQL使用%s占位符,即使密码中包含单引号等特殊字符,也不会破坏SQL结构,这是防止SQL注入最基本的手段。self.win.destroy()关闭登录窗口后创建主窗口实例,这是tkinter中切换窗口的常用做法。

参数说明:show="*"让输入框以密文显示。sticky=tk.E让控件贴右对齐,布局看起来更整齐。resizable(False, False)固定窗口大小,避免登录界面被拉伸变形。这段代码放在login.py里,直接运行就能看到窗口。

3.2 主窗口布局:tkinter左侧导航栏模板

你搜索“tkinter左侧导航栏模板”得到的方案,基本都用类似思路:窗口左右分栏,左边固定宽度放菜单按钮,右边放内容区。我习惯用ttk.PanedWindow来做分栏,方便拖动,也更接近桌面应用的感觉。

import tkinter as tk from tkinter import ttk class MainWindow: def __init__(self, user): self.user = user self.win = tk.Tk() self.win.title("图书管理系统") self.win.geometry("900x600") self.paned = ttk.PanedWindow(self.win, orient=tk.HORIZONTAL) self.paned.pack(fill=tk.BOTH, expand=True) # 左侧导航栏 self.nav_frame = ttk.Frame(self.paned, width=160) self.nav_frame.pack_propagate(False) # 固定宽度,防止子控件撑大 self.paned.add(self.nav_frame, weight=0) # 右侧内容区 self.content_frame = ttk.Frame(self.paned) self.paned.add(self.content_frame, weight=1) buttons = [ ("图书管理", self.show_books), ("借阅管理", self.show_borrows), ("用户管理", self.show_users), ] for text, cmd in buttons: ttk.Button(self.nav_frame, text=text, command=cmd).pack( fill=tk.X, padx=10, pady=5) self.show_books() def switch_page(self, page_frame): for child in self.content_frame.winfo_children(): child.destroy() page_frame.pack(fill=tk.BOTH, expand=True) def show_books(self): from pages.book_page import BookPage self.switch_page(BookPage(self.content_frame))

逻辑说明:pack_propagate(False)是让Frame的宽度不随子控件变化,保证导航栏稳定在160像素。switch_page先清空右侧所有子控件,再放入新页面,这就是一个简单的单页应用效果。每个页面都是一个继承自ttk.Frame的类,相互独立,方便维护。

参数说明:weight=0weight=1是PanedWindow为左右区域分配额外空间的比重。拖动窗口时,右侧内容区会等比扩大,左侧保持原始宽度。这个结构同样适合通讯录管理、商品管理等任何管理类项目,替换按钮文字和页面类即可。

3.3 Treeview表格展示与增删改查

图书列表的核心控件是ttk.Treeview,它支持多列展示、单选多选、绑定滚动条。下面的代码展示表格初始化和添加图书的完整路径。

import tkinter as tk from tkinter import ttk, messagebox from db import get_connection class BookPage(ttk.Frame): def __init__(self, master): super().__init__(master) self.columns = ("id", "isbn", "title", "author", "publisher", "category", "available", "total") self.tree = ttk.Treeview(self, columns=self.columns, show="headings", height=15) self.tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) headings = {"id": "ID", "isbn": "ISBN", "title": "书名", "author": "作者", "publisher": "出版社", "category": "分类", "available": "可借", "total": "总量"} widths = {"id": 40, "isbn": 110, "title": 180, "author": 80, "publisher": 100, "category": 60, "available": 60, "total": 60} for col in self.columns: self.tree.heading(col, text=headings[col]) self.tree.column(col, width=widths[col], anchor=tk.CENTER) self.refresh_books() def refresh_books(self): for item in self.tree.get_children(): self.tree.delete(item) sql = ("SELECT id, isbn, title, author, publisher, category, " "available, total FROM book ORDER BY id") conn = get_connection() with conn.cursor() as cursor: cursor.execute(sql) rows = cursor.fetchall() conn.close() for row in rows: self.tree.insert("", tk.END, values=tuple(row.values())) def add_book(self): title = self.title_var.get().strip() if not title: messagebox.showwarning("提示", "书名不能为空") return total = self.total_var.get().strip() if not total.isdigit() or int(total) < 1: messagebox.showwarning("提示", "总量必须是大于0的整数") return sql = ("INSERT INTO book (isbn, title, author, publisher, category, total) " "VALUES (%s, %s, %s, %s, %s, %s)") try: conn = get_connection() with conn.cursor() as cursor: cursor.execute(sql, (self.isbn_var.get().strip(), title, self.author_var.get().strip(), self.publisher_var.get().strip(), self.category_var.get().strip(), int(total))) conn.commit() conn.close() self.refresh_books() messagebox.showinfo("成功", "添加成功") except Exception as e: messagebox.showerror("错误", str(e))

逻辑说明:show="headings"表示只显示列头,不显示Treeview左侧的树形层级。refresh_books先清空现有行再全量查询,数据量少时简单可靠。插入新书前做了两处校验:书名非空、总量是正整数,避免脏数据进库。integeravailable的初始值默认等于total,所以插入时只写了total

参数说明:anchor=tk.CENTER让列内容居中。height=15表示表格显示15行,超出部分需要滚动条。你可以在refresh_books调用前创建垂直滚动条:vsb = ttk.Scrollbar(self, orient=tk.VERTICAL, command=self.tree.yview),再设置self.tree.configure(yscrollcommand=vsb.set),这样数据多时也能流畅查看。

4. 让系统更稳的细节:模糊查询、分页和事务处理

4.1 模糊查询与参数化SQL,防止SQL注入

图书管理系统的查询框是必做模块,最常见的是按书名或作者模糊查找。新手常犯的错误是直接拼接字符串:

# 错误示范,绝对不能这么写 sql = "SELECT * FROM book WHERE title LIKE '%{}%'".format(keyword)

keyword里如果包含单引号,轻则查询报错,重则被构造出' OR 1=1 --这样的注入攻击。正确写法是把通配符合并进参数值,再通过占位符传参:

def search_books(self, keyword): sql = ("SELECT id, isbn, title, author, publisher, category, " "available, total FROM book " "WHERE title LIKE %s OR author LIKE %s") like_kw = f"%{keyword}%" conn = get_connection() with conn.cursor() as cursor: cursor.execute(sql, (like_kw, like_kw)) rows = cursor.fetchall() conn.close() return rows

逻辑说明:%s是pymysql的占位符,like_kw在传参前拼接通配符。这样既实现了LIKE模糊搜索,又让pymysql对参数做安全转义,恶意文本进入不了SQL执行体。如果用户输入了%_,它们会被当成MySQL通配符,但不会破坏查询结构,在图书管理这种低安全级别的场景下影响可以忽略。

参数说明:这里的LIKE %s默认为非二进制字符集的忽略大小写匹配。如果你在mysql创建索引时对title做了索引,LIKE 'abc%'才走索引,而LIKE '%abc%'通常触发全表扫描,这是MySQL的索引规则,和数据量无关。

4.2 分页查询:LIMIT与COUNT的组合

当图书数据超过一两百条,一次性加载到Treeview会明显卡顿。分页需要两个动作:查询当前页数据,以及统计总数计算总页数。我习惯封装一个分页类:

class Pagination: def __init__(self, page_size=20): self.page_size = page_size self.current_page = 1 self.total_pages = 1 self.total_count = 0 def load_data(self, keyword=None): base_sql = "FROM book WHERE 1=1" params = [] if keyword: base_sql += " AND (title LIKE %s OR author LIKE %s)" like = f"%{keyword}%" params.extend([like, like]) conn = get_connection() with conn.cursor() as cursor: # 先查总数 cursor.execute(f"SELECT COUNT(*) AS cnt {base_sql}", params) self.total_count = cursor.fetchone()['cnt'] self.total_pages = max(1, (self.total_count + self.page_size - 1) // self.page_size) if self.current_page > self.total_pages: self.current_page = self.total_pages # 再查当前页 offset = (self.current_page - 1) * self.page_size cursor.execute(f"SELECT * {base_sql} ORDER BY id LIMIT %s, %s", params + [offset, self.page_size]) rows = cursor.fetchall() conn.close() return rows

逻辑说明:base_sql只写表名和WHERE条件,这样COUNT(*)SELECT *能复用同一套参数。总数算完后计算总页数,如果当前页超出总页数就回退到最后一页。注意LIMIT的两个参数也通过占位符传入,防止数字部分被注入。

参数说明:page_size=20是经验值。Treeview在渲染50个以上item时,滚动会有可见的掉帧。答辩演示时保持20比较稳妥。如果你的系统有上千册书,还可以把page_size做成下拉框,让老师自己选每页显示条数。

4.3 借阅归还中的事务处理

借书动作包含两个写操作:向borrow表插入记录,同时把book表的available减1。任何一个失败都会导致数据不一致,所以必须放在事务里:

from datetime import datetime, timedelta def borrow_book(self, user_id, book_id): conn = get_connection() try: conn.begin() with conn.cursor() as cursor: # 锁定该图书当前行,防止并发超借 sql_check = "SELECT available FROM book WHERE id=%s FOR UPDATE" cursor.execute(sql_check, (book_id,)) row = cursor.fetchone() if not row or row['available'] <= 0: raise ValueError("没有可借的库存") due_date = datetime.now() + timedelta(days=30) sql_insert = ("INSERT INTO borrow (user_id, book_id, due_date) " "VALUES (%s, %s, %s)") cursor.execute(sql_insert, (user_id, book_id, due_date)) sql_update = "UPDATE book SET available = available - 1 WHERE id=%s" cursor.execute(sql_update, (book_id,)) conn.commit() return True except Exception: conn.rollback() raise finally: conn.close()

逻辑说明:SELECT ... FOR UPDATEbook这一行加排他锁,直到事务提交或回滚。两个同学同时点借同一本书时,第二个事务会等待第一个提交后拿到最新的available值,从而判断出库存是否为0。这是最直观的并发控制方案,答辩时能自然引出“锁”和“隔离级别”这两个概念。

参数说明:timedelta(days=30)是默认借期,可以从配置表读取。归还操作和借书对称:把borrow表的return_date更新为当前时间,status改为returned,再把book表的available加1,同样需要事务。这里再次强调,db_config里的autocommit必须为False,否则conn.begin()无效,事务也就形同虚设。

如果你想进一步简化调用,可以把借阅逻辑写成MySQL存储过程,通过cursor.callproc('borrow_book', (user_id, book_id))触发。这种做法把事务控制移动到数据库端,但调试时需要在mysql命令行单独验证存储过程,增加了一定的开发成本。我一般还是用Python层的事务,可读性和维护性更好。

4.4 MySQL连接参数与索引优化

当借阅记录到达万级以后,查询速度会明显下跌。不要盲目调服务器内存,先用数据库命令定位瓶颈。常用的mysql数据库命令大全里,EXPLAINSHOW INDEXSHOW PROCESSLIST是排查的三板斧。下面是我的调优清单:

参数/操作推荐值/做法效果
max_connections50-100防止连接池占满导致“Too many connections”
wait_timeout配合连接池ping连接被服务端断开后自动重连
innodb_buffer_pool_size物理内存的50%-70%InnoDB缓存表数据与索引,降低磁盘IO
复合索引(user_id, status)加速“某用户未还的书”查询
EXPLAIN检查type是否为refrange判断索引是否生效

EXPLAIN验证索引是否生效:

EXPLAIN SELECT * FROM borrow WHERE user_id=3 AND status='borrowed';

如果结果里typeALL,说明全表扫描;此时应在borrow表上执行ALTER TABLE borrow ADD INDEX idx_user_borrow (user_id, status),再跑一次EXPLAIN,通常就会变成type=ref。这组对照能写进课程设计的测试报告,比单纯贴截图有说服力。

5. 打包exe避开坑:PyInstaller参数和配置文件外置

代码写完后的临门一脚是打包成exe,否则老师电脑上没有Python环境就没法演示。我常用的打包命令是:

pyinstaller -F -w --icon=library.ico -n 图书管理系统 main.py

参数说明:-F把所有依赖打进一个exe文件,方便拷贝;-w让程序运行时不弹出黑色控制台窗口;--icon指定图标;-n设置生成的程序名。打包完成后,dist目录下会生成“图书管理系统.exe”,直接双击运行。

打包最常见的坑有两个。第一个是pymysql模块找不到,解决办法是在main.py文件最顶部主动写import pymysql,因为PyInstaller静态分析时无法识别某些动态导入的子模块。第二个是图标文件路径问题,建议图标放在和main.py同级的目录,打包时使用相对路径而不是绝对路径,否则换一台机器图标就会消失。

为了让exe能在不同MySQL环境上跑起来,我建议把数据库连接配置外置到一个config.ini,程序启动时动态读取,避免每次改密码都重新打包:

import configparser import os def load_config(): conf = configparser.ConfigParser() conf_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.ini") conf.read(conf_file, encoding="utf-8") return { 'host': conf.get('mysql', 'host', fallback='localhost'), 'user': conf.get('mysql', 'user', fallback='root'), 'password': conf.get('mysql', 'password', fallback=''), 'database': conf.get('mysql', 'database', fallback='library_db'), }

配置文件内容:

[mysql] host = localhost user = root password = 123456 database = library_db

集成到db.py时,在构造db_config之前调用load_config(),就能替换硬编码的字典。打包时把config.ini放在exe同目录,老师换到自己的机器后只需要改用户名和密码,不需要重新打包。

答辩前多做一个加分小功能:在系统里增加“数据统计”页面,用聚合查询展示各个分类的图书数量和借出情况。例如:

SELECT category, COUNT(*) AS total, SUM(CASE WHEN available < total THEN 1 ELSE 0 END) AS borrowed_count FROM book GROUP BY category;

把这段SQL的结果渲染成表格或简单的柱状图,老师会默认你掌握了聚合查询和子查询的综合运用。这样整个项目从界面到数据库再到打包发布,每个环节都有可以展开讲的技术细节。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 4:32:04

Claude Code 配 TaoToken:体验 GLM-5.2 百万级上下文编码

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 4:31:59

2026代码模型横评:火山引擎综合成本直降80%的实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 4:30:47

STC89C52驱动TC35发中文短信的嵌入式实现

简介&#xff1a;本资源是一个基于STC89C52单片机实现中文短信发送的嵌入式开发项目&#xff0c;面向电子工程、物联网及单片机初学者与实践者&#xff0c;解决在资源受限MCU上处理中文编码、串口通信与GSM模块AT指令交互等典型难题。压缩包共25个文件&#xff0c;含3个核心C源…

作者头像 李华
网站建设 2026/9/14 4:30:38

声纹识别中的self-attention:从注意力池化到工程落地

简介&#xff1a;基于深度学习的声纹识别&#xff08;自注意力机制&#xff09;算法资源&#xff0c;专注于说话人识别任务&#xff0c;代码为Python编写&#xff0c;覆盖高斯混合模型、GMM-UBM、i-vector等传统统计方法&#xff0c;以及基于自注意力的深度学习方法&#xff0c…

作者头像 李华
网站建设 2026/9/14 4:30:28

WorkBuddy金融版实测:金融行业Agent落地与合规破局

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华