☰
Python+SQL Server+Tkinter:桌面图书管理系统完整方案
2026/10/3 9:22:39 网站建设 项目流程

简介:基于Python开发的桌面图书管理系统完整项目包,面向需要完成课程设计或毕业设计的计算机相关专业学生,也适合正在学习Python图形界面开发与数据库应用的开发者参考。系统覆盖图书入库、查询、借书、还书、借书证管理等核心业务流程,采用Microsoft SQL Server 2019作为数据库管理系统,使用Python 3.6作为宿主语言,并在PyCharm编译环境中完成编码与调试,整体是一个功能完整的桌面应用实战案例。压缩包内共2000个文件,压缩包大小65.71MB,主要包含大量.py源码文件、编译生成的.pyc字节码与.pyd扩展模块,以及SQL数据库脚本、Word设计报告和程序运行所需的dll动态库、exe可执行组件,目录层次清晰,便于按模块查阅和二次开发。已有2290人浏览学习。资源内含完整的设计报告、可运行源码与数据库备份,可借此梳理Python与SQL Server的数据交互方式、界面事件绑定、图书数据增删改查等实现细节,适合作为毕业设计基础工程或进一步扩展功能的学习蓝本。

1. 桌面图书管理系统:课程设计与小型书库管理的那套 Python 方案

如果你正在找一份能直接运行、又能写进课程设计报告的图书管理系统源码,这套基于 Python 3.6 + SQL Server 2019 + Tkinter 的桌面图书管理系统值得花半小时拆一遍。它覆盖了图书入库、模糊查询、借书、还书、借书证办理与挂失这几条核心业务线,不是那种只有一个登录页的 demo,而是带完整数据库文件、设计报告 docx 和源码包的交付物。适合三类人:初次做课程设计的学生、想给单位或家里小书库做一套轻量管理工具的人,以及想把"数据库操作 + GUI 编程"串成一个完整项目的自学者。尤其有设计报告文档这一点,能省掉不少写文档的时间。

2. 技术选型与工程结构:为什么是 Python 3.6 + SQL Server + Tkinter

2.1 SQL Server 2019 而不是 MySQL/SQLite:课程设计场景下的现实选择

先说数据库。这套系统的核心是 Microsoft SQL Server 2019 Developer 版。很多人第一反应是"为什么不用 SQLite 或 MySQL",但放在课程设计和桌面工具这个场景里,SQL Server 有三个实实在在的理由。

第一,SQL Server Developer 版本对个人开发完全免费,而且功能上和正式版没有差异,对做课程设计来说不存在授权问题。第二,它的图形化管理工具 SSMS(SQL Server Management Studio)对新手极其友好,建库、建表、备份、附加数据库都可以用鼠标完成,比起 MySQL 的命令行或者复杂的客户端配置,学习成本低得多。第三,很多学校的数据库课程就是拿 SQL Server 教的,选它意味着你的设计报告和答辩内容能和课程知识直接对口,老师问起来"为什么选这个数据库"时,你能讲出实际选型逻辑。

但要注意,SQL Server 是服务端数据库,不是像 SQLite 那样嵌入式的单文件数据库。这意味着你的 Python 程序运行时,本机(或局域网内)必须有一个正在运行的 SQL Server 实例。这套资源里附带数据库文件,导入方式通常是直接附加 .mdf 文件,或者在 SQL Server 里执行建库脚本。日常使用时,你需要保证 SQL Server 服务处于启动状态,否则程序一启动就会报连接失败。

提示:如果你的机器上没装 SQL Server 2019,先去微软官网下载 Developer 版,安装时选择"默认实例"就好。安装完再用 SSMS 验证一次能否用 Windows 身份验证登录。

2.2 Python 3.6 与 pymssql 驱动的兼容性逻辑

宿主语言选的是 Python 3.6。这个版本现在看偏老,但在这套系统里恰恰是稳妥的选择。原因在于 SQL Server 的 Python 数据库驱动 pymssql,在 Python 3.6 环境下有非常成熟的预编译 wheel 包,pip install pymssql 一行就能装好,不需要本机装 C 编译器。

我见过太多人用 Python 3.10+ 去连 SQL Server,然后在安装 pyodbc 或 pymssql 时遇到编译报错——"Microsoft Visual C++ 14.0 is required",直接卡住。用 Python 3.6 基本绕开了这个问题。如果你已经装了新版 Python,我建议按这套资源的约定单独装一个 3.6 的解释器,或者用 conda 创建 python=3.6 的虚拟环境。PyCharm 里配环境也很简单:Settings -> Project Interpreter -> Add,选择已装好的 Python 3.6 路径即可。

2.3 工程目录与模块划分:照着这个结构写不改也跑得通

解压资源包后,你会看到设计报告 docx、数据库文件、还有 Python 源码。源码部分的目录结构大致是主程序文件加若干个模块文件。我拆过类似的课程设计项目,比较规范的模块划分方式是把数据库连接、业务逻辑、界面代码分开,而不是全部写在一个文件里。参照这套资源的命名习惯,典型的工程结构长这样:

library_system/ ├── db_helper.py # 数据库连接与通用查询封装 ├── auth.py # 登录、借书证办理/挂失相关逻辑 ├── book_service.py # 图书入库、查询、借书、还书业务 ├── ui_main.py # Tkinter 主界面 └── ui_dialogs.py # 借书/还书/办证的对话框窗口

拆分的好处有两个:一是你改业务逻辑时不用在几百行的界面代码里翻找,二是写设计报告时可以按模块讲述"表现层-业务层-数据访问层"的三层结构,答辩时很加分。实际运行入口是 ui_main.py,启动后先调用 db_helper 里的连接函数做一次连通性检查,失败了就弹窗提示,不会让用户面对一堆晦涩的报错堆栈。

3. 数据库建模:四张表把借书还书的边界条件立住

3.1 核心表结构设计:从图书到借阅记录的状态流转

图书管理系统的数据模型,核心是回答四个问题:书库里有什么书、谁有借书证、谁借走了什么书、这本书现在在谁手里。这套系统的数据库文件里,表的设计思路也是围绕这四个问题展开的。主表主要有四张:图书表、借书证表、借阅记录表,外加一张管理员表。

图书表(BookInfo)的关键字段如下:

字段名类型说明
BookIDint 自增主键图书唯一编号
ISBNvarchar(20)国际标准书号
BookNamevarchar(100)书名
Authorvarchar(50)作者
Publishervarchar(100)出版社
PublishDatedate出版日期
TotalCountint馆藏总数
AvailableCountint当前可借数量

借书证表(BorrowCard)记录每个借阅人的身份:

字段名类型说明
CardIDint 自增主键借书证编号
ReaderNamevarchar(50)借阅人姓名
Phonevarchar(11)联系电话
RegDatedatetime办证日期
Statustinyint1 正常,0 挂失

借阅记录表(BorrowRecord)是系统里最活跃的一张表,每次借书插入一条记录,还书时更新归还日期:

字段名类型说明
RecordIDint 自增主键流水号
BookIDint 外键借走的图书编号
CardIDint 外键借书证编号
BorrowDatedatetime借书时间
DueDatedatetime应还日期
ReturnDatedatetime实际归还日期,NULL 表示未还
Finedecimal(8,2)逾期罚款,默认 0

这三张表加一张管理员表,能覆盖摘要里提到的全部功能:图书入库对应 INSERT 到 BookInfo,查询对应 SELECT,借书对应 INSERT BorrowRecord 且同时 UPDATE BookInfo.AvailableCount,还书对应 UPDATE BorrowRecord.ReturnDate 和 BookInfo.AvailableCount,借书证管理的办理、挂失则对应 BorrowCard 的增改。

3.2 建库建表脚本:参数含义与执行方式

数据库文件虽然可以直接附加进 SQL Server,但作为开发习惯,我建议你把建表脚本也留一份。这样哪怕 .mdf 文件因版本问题附加失败,也能靠脚本重新生成库结构。以下是核心建表脚本(节选图书表和借阅记录表):

-- 创建图书表 CREATE TABLE BookInfo ( BookID INT IDENTITY(1,1) PRIMARY KEY, ISBN VARCHAR(20) NOT NULL, BookName VARCHAR(100) NOT NULL, Author VARCHAR(50), Publisher VARCHAR(100), PublishDate DATE, TotalCount INT NOT NULL DEFAULT 1, AvailableCount INT NOT NULL DEFAULT 1 ); -- 创建借书证表 CREATE TABLE BorrowCard ( CardID INT IDENTITY(10001,1) PRIMARY KEY, ReaderName VARCHAR(50) NOT NULL, Phone VARCHAR(11), RegDate DATETIME DEFAULT GETDATE(), Status TINYINT DEFAULT 1 -- 1=正常 0=挂失 ); -- 创建借阅记录表 CREATE TABLE BorrowRecord ( RecordID INT IDENTITY(1,1) PRIMARY KEY, BookID INT NOT NULL REFERENCES BookInfo(BookID), CardID INT NOT NULL REFERENCES BorrowCard(CardID), BorrowDate DATETIME DEFAULT GETDATE(), DueDate DATETIME, ReturnDate DATETIME NULL, Fine DECIMAL(8,2) DEFAULT 0 );

关键参数说明:Identity(1,1) 表示自增列从 1 开始每次加 1,借书证从 10001 开始是为了借书证号看起来更正式。varchar(11) 的 Phone 字段只考虑了 11 位手机号,如果将来要存固话或分机号会出现截断。AvailableCount 与 TotalCount 分开设计是很重要的一步——TotalCount 记录馆藏总量,AvailableCount 记录当前可借量,避免每次借还书都重算库存。

3.3 借还书的状态流转:为什么要用 ReturnDate 而不是删除记录

借书与还书的核心约束在 BorrowRecord 表上。很多新手设计时会犯一个错误:图书归还后把借阅记录 DELETE 掉,这样虽然能保证"当前借出表"干净,但历史追溯全部丢失,无法回答"这本书这个月被借了多少次"这样的统计问题。

正确做法是用 ReturnDate 字段标记状态:NULL 表示在借,非 NULL 表示已还。图书可借数量则用 AvailableCount 单独维护。每次借书时先检查 AvailableCount 是否大于 0,再执行插入记录和扣减库存两步;还书时更新 ReturnDate 并把库存加回。为了保证这两步的原子性,应该放在同一个数据库事务里,这也是代码部分要重点实现的逻辑。

-- 借书事务示例 BEGIN TRANSACTION; UPDATE BookInfo SET AvailableCount = AvailableCount - 1 WHERE BookID = 101 AND AvailableCount > 0; IF @@ROWCOUNT = 0 BEGIN ROLLBACK; THROW 50001, '库存不足', 1; END INSERT INTO BorrowRecord (BookID, CardID, DueDate) VALUES (101, 10001, DATEADD(DAY, 30, GETDATE())); COMMIT;

这段 SQL 里最关键的是 UPDATE 语句中AvailableCount > 0这个条件。它不是一个简单的检查,而是借书时防止超卖的锁机制。如果库存已经被借完,UPDATE 影响的行数为 0,事务回滚,不会产生脏数据。

注意:像这样把业务规则写进 SQL 可以保证并发安全,但桌面单机系统的并发量其实很低,更多人会直接把判断写在 Python 代码里。我的建议是两种都保留——代码里做前置校验负责用户体验,SQL 里的条件负责数据安全兜底。

4. 核心功能落地:连接、登录、入库、查询与借还书代码怎么写

4.1 数据库连接封装:pymssql 的连接参数与复用

这套系统用的是 pymssql 库。连接 SQL Server 时,最关键的是 server、user、password、database 四个参数,以及 charset 要显式指定为 utf8,否则从数据库读出来的中文在界面上可能显示为一堆问号。以下是一段标准的连接封装代码:

import pymssql def get_connection(): """ 返回一个 pymssql 连接对象 使用前请确认 SQL Server 的 TCP/IP 协议已启用 """ conn = pymssql.connect( server='localhost', # 本机 SQL Server 实例 user='sa', # 数据库登录账号 password='123456', # 对应密码 database='LibraryDB', # 数据库名称 charset='utf8', # 解决中文乱码 login_timeout=10, # 登录超时10秒 as_dict=True # 查询结果以字典形式返回 ) return conn

这里的as_dict=True值得说一下:设置后查询返回的每一行是字段名到值的字典,写代码时可以row['BookName']而不是row[1],可读性强很多,也避免了表结构调整后下标错位的问题。login_timeout=10防止 SQL Server 服务未启动时程序长时间卡住没反应。

我一般还会在封装层加一个全局连接变量,每次操作复用同一个连接而不是频繁开关。桌面系统同时只有一个用户,一个连接足够,频繁创建连接的开销反而大。但要注意,连接空闲时间过长会被 SQL Server 断开,如果出现"查询到一半报连接已关闭"的问题,在查询前加一个重连判断即可。

4.2 登录与借书证管理:校验、办证、挂失的代码骨架

登录逻辑不复杂,管理员的账号密码存管理员表。但借书证管理有细节:办证时检查手机号格式和是否重复,挂失时不是删除记录而是把 Status 置 0,这样才能保留办证历史。以下代码用 tkinter 的 messagebox 提供界面反馈:

def login(username, password): conn = get_connection() cursor = conn.cursor() # 参数化查询防止 SQL 注入,不要用字符串拼接 sql = "SELECT AdminID FROM AdminInfo WHERE UserName=%s AND Pwd=%s" cursor.execute(sql, (username, password)) row = cursor.fetchone() conn.close() if row: return True return False def register_card(reader_name, phone): # 检查手机号是否已存在 conn = get_connection() cursor = conn.cursor() check_sql = "SELECT COUNT(*) AS cnt FROM BorrowCard WHERE Phone=%s" cursor.execute(check_sql, (phone,)) if cursor.fetchone()['cnt'] > 0: return "该手机号已办理过借书证" insert_sql = "INSERT INTO BorrowCard(ReaderName, Phone) VALUES(%s, %s)" cursor.execute(insert_sql, (reader_name, phone)) conn.commit() conn.close() return "办理成功"

注意这里全部用了%s占位符加参数元组的写法,而不是'%s'字符串格式化拼 SQL 字符串。课程设计里很多人省事直接拼接,但这种写法一旦遇到用户名里带单引号就会报错,更严重的会被构造 SQL 注入。答辩时老师问"你考虑了安全吗",把参数化写法讲出来是很加分的点。挂失的逻辑就是UPDATE BorrowCard SET Status = 0 WHERE CardID = %s,与办证的 INSERT 结构一致,不再重复。

4.3 图书入库与模糊查询:INSERT 与 LIKE 的边界处理

图书入库界面一般是一组 Entry 控件收集字段后点击"添加"按钮。入库前要处理两个问题:ISBN 重复的书是新增一条还是累加库存?这套系统的做法偏向累加库存,即 ISBN 存在时更新 TotalCount 和 AvailableCount,不存在时插入新记录。这个逻辑用 SQL 的 EXISTS 判断实现:

def add_book(book_info): # book_info: dict,包含 isbn/book_name/author/publisher/publish_date conn = get_connection() cursor = conn.cursor() isbn = book_info['isbn'] check_sql = "SELECT BookID FROM BookInfo WHERE ISBN=%s" cursor.execute(check_sql, (isbn,)) exists = cursor.fetchone() if exists: # 已存在:库存+1 update_sql = """ UPDATE BookInfo SET TotalCount=TotalCount+1, AvailableCount=AvailableCount+1 WHERE ISBN=%s """ cursor.execute(update_sql, (isbn,)) else: insert_sql = """ INSERT INTO BookInfo(ISBN, BookName, Author, Publisher, PublishDate) VALUES(%s, %s, %s, %s, %s) """ cursor.execute(insert_sql, ( isbn, book_info['book_name'], book_info['author'], book_info['publisher'], book_info['publish_date'] )) conn.commit() conn.close()

图书查询功能的关键是模糊查询。WHERE BookName LIKE '%' + %s + '%'在 pymssql 中的写法要小心,因为%s是驱动占位符,而%是 SQL 通配符,两者混在一起容易写错。正确做法是:

def search_book(keyword): conn = get_connection() cursor = conn.cursor() # % 通配符放在参数里,%s 只做占位 sql = """ SELECT BookID, BookName, Author, Publisher, TotalCount, AvailableCount FROM BookInfo WHERE BookName LIKE %s OR Author LIKE %s """ like_keyword = f"%{keyword}%" cursor.execute(sql, (like_keyword, like_keyword)) rows = cursor.fetchall() conn.close() return rows

这里把%拼进 like_keyword 变量,然后整体作为一个参数传进去。如果写成"SELECT ... LIKE '%" + keyword + "%'",当 keyword 里含单引号时整个查询直接报错,妥妥的翻车现场。另外两个 LIKE 条件用 OR 连接,覆盖按书名和按作者两种查询场景,界面上的输入框不需要做区分,老师演示时随手输入任意关键字都能查到结果。

4.4 借书与还书:事务、库存扣减与逾期费用计算的实现

借书是整个系统里最该谨慎的功能。它涉及三步:检查借书证状态和可借额度、检查图书库存、扣减库存并插入借阅记录。这三步用 Python 代码实现时,必须在同一个事务里完成。pymssql 默认会自动提交每条语句,所以需要手动关闭自动提交:

def borrow_book(book_id, card_id): conn = get_connection() # 开启事务 conn.autocommit(False) cursor = conn.cursor() # 第一步:检查借书证状态 card_sql = "SELECT Status FROM BorrowCard WHERE CardID=%s" cursor.execute(card_sql, (card_id,)) card_row = cursor.fetchone() if not card_row or card_row['Status'] != 1: conn.rollback() conn.close() return "借书证不存在或已挂失" # 第二步:检查库存并扣减 update_sql = """ UPDATE BookInfo SET AvailableCount=AvailableCount-1 WHERE BookID=%s AND AvailableCount>0 """ cursor.execute(update_sql, (book_id,)) if cursor.rowcount == 0: conn.rollback() conn.close() return "该书已无可借库存" # 第三步:插入借阅记录,默认借期30天 insert_sql = """ INSERT INTO BorrowRecord(BookID, CardID, DueDate) VALUES(%s, %s, DATEADD(DAY, 30, GETDATE())) """ cursor.execute(insert_sql, (book_id, card_id)) conn.commit() conn.close() return "借书成功"

cursor.rowcount在 pymssql 里返回 UPDATE 影响的行数,这是判断库存扣减是否成功的依据。还有一个可借额度的判断:比如系统规定每个借书证最多同时借 5 本,需要先执行SELECT COUNT(*) FROM BorrowRecord WHERE CardID=%s AND ReturnDate IS NULL,如果结果超过 5 就拒绝借书。这一步应该在检查库存之前完成,顺序是"证件状态 -> 可借额度 -> 库存",这样用户能尽快得到反馈,而不是等到最后一步才被告知借不了了。

还书逻辑相对简单,更新 ReturnDate 和库存加回两步:

def return_book(record_id, book_id): conn = get_connection() conn.autocommit(False) cursor = conn.cursor() update_sql = "UPDATE BorrowRecord SET ReturnDate=GETDATE() WHERE RecordID=%s AND ReturnDate IS NULL" cursor.execute(update_sql, (record_id,)) if cursor.rowcount == 0: conn.rollback() conn.close() return "记录不存在或已归还" # 把可借数量加回去 back_sql = "UPDATE BookInfo SET AvailableCount=AvailableCount+1 WHERE BookID=%s" cursor.execute(back_sql, (book_id,)) conn.commit() conn.close() return "还书成功"

逾期罚款的规则在代码里做了简化:默认借期 30 天,超过 30 天未还每天罚 0.1 元。实际计算是在还书时执行的:DATEDIFF(DAY, DueDate, GETDATE())大于 0 就乘以 0.1 写入 Fine 字段。如果你想改罚金标准,找到还书函数里计算 Fine 的那一行改乘数即可。

提示:很多课程设计查重时会看借书还书是不是放在同一事务里。如果你把"扣库存"和"插记录"写成两条独立的自动提交语句,书少了一本但记录没插上,这种逻辑漏洞在答辩演示时很容易被老师追问出来。

5. 常见问题与避坑:跑通这套系统的五个典型现场

5.1 pymssql 安装失败:MSVC 编译器报错

现象:执行pip install pymssql或pip install pyodbc时,终端弹出"The current version of the Microsoft C++ compiler is required"之类的大段红字。

原因:新版 Python 下某些数据库驱动没有预编译的 wheel 包,需要本机安装 Visual C++ Build Tools 才能从头编译。

解决:这套资源锁定 Python 3.6 的原因就在这里——Python 3.6 配套的 pymssql 有现成 wheel 包,pip install pymssql不会碰编译器。如果你用的是 3.8 及以上版本,先去https://pypi.org/project/pymssql/#files页面找对应版本号的 .whl 文件下载,再本地安装。还要注意 pymssql 是 32 位还是 64 位,必须和 Python 解释器位数一致,否则 import 阶段直接报"ModuleNotFoundError"或"DLL load failed"。

5.2 连接 SQL Server 失败:无法连接到 localhost

现象:程序一启动就弹"无法连接数据库"或 pymssql 抛出OperationalError: (20002, ...)。

原因:SQL Server 默认不开启 TCP/IP 协议。pymssql 走的是 TCP 连接,本地连接也不例外。另外 SQL Server 服务本身也可能没启动。

解决:打开"SQL Server 配置管理器",找到"SQL Server 网络配置"下的"协议",把 TCP/IP 启用状态改为"已启用",然后重启 SQL Server 服务。配置管理器可以在 Windows 开始菜单的"SQL Server 文件夹"里找到。如果启了 TCP/IP 还报错,用命令行net start MSSQLSERVER确认服务处于运行状态。这一步是新手最容易卡住的地方,因为 SQL Server Management Studio 能连接不代表 pymssql 能连接,两套机制不同。

5.3 中文显示乱码:界面上的书名全部变成问号

现象:数据库里看中文正常,Python 查询打印也正常,但 Tkinter 界面上显示乱码或问号。

原因:pymssql 连接时默认字符集可能不是 UTF-8,SQL Server 实例的排序规则也影响数据存储方式。

解决:连接时强制指定charset='utf8',建库时把数据库排序规则设为Chinese_PRC_CI_AS。如果数据库已经建好了,执行ALTER DATABASE LibraryDB COLLATE Chinese_PRC_CI_AS可以改排序规则。Tkinter 本身对中文支持没问题,乱码源头一定在连接层或数据库层,优先排查这两处。注意 Python 源码文件本身也要保存为 UTF-8 编码,PyCharm 右下角可以查看当前文件编码,改成 UTF-8 再重写中文。

5.4 图书借出后库存变负数

现象:明明库存只有 1 本,连续借了 3 次都提示成功,随后 AvailableCount 变成负数。

原因:检查库存和扣减库存是两条独立 SQL,中间没有事务保护,也没有在 UPDATE 里加AvailableCount > 0条件。并发点击借书按钮时,两次请求都读到库存为 1,执行了两次扣减。

解决:用第 4 章的写法,把扣减合并到一条带条件判断的 UPDATE 里,配合rowcount判断是否真的扣成功。只要 UPDATE 的是AvailableCount = AvailableCount - 1 ... WHERE AvailableCount > 0,数据库层面的原子性就能兜底,即使 Python 代码开了多线程同时点借书,也不会超卖。同时把借书按钮设置一个防抖标志,点击后立即禁用半秒,治标。

5.5 PyInstaller 打包成 exe 后报缺依赖

现象:开发环境运行正常,用 PyInstaller 打包后在别的机器上双击无反应,或命令行运行提示ModuleNotFoundError: No module named 'pymssql'。

原因:PyInstaller 自动收集依赖时没把 pymssql 的动态库带进包。pymssql 是 C 扩展,内部依赖 FreeTDS 客户端库,PyInstaller 的分析器经常漏掉这类二进制依赖。

解决:打包命令里显式指定隐藏导入:pyinstaller --hidden-import pymssql -F ui_main.py。如果还不行,在 spec 文件里手动添加 pymssql 的路径到 binaries。更省事的办法是打包后用资源包里自带的 exe 版本,把源码打包这一步放到功能验证通过之后再去折腾。

6. 从源码到可用:启动校验、数据还原与一键打包的收尾习惯

拿到这套资源后,按什么顺序去折腾,决定了你是一小时内跑起来还是卡一个晚上。我建议的流程是:先还原数据库,再跑源码,最后根据报错调整。

第一步是打开 SSMS,连接 SQL Server 实例,右键"数据库"节点选"附加",把资源包里的 .mdf 文件附加进去。附加成功后检查一下表是否齐全。如果不方便附加,直接找包里带 .sql 文件的话,在 SSMS 里打开执行一遍也能建出同样的库。附加和脚本执行这两种方式,脚本方式对 SQL Server 版本兼容性更好。第二步是打开 PyCharm,用 Python 3.6 解释器建一个虚拟环境,在终端执行pip install pymssql,然后打开 ui_main.py 直接运行。第三步如果报连接失败,按第 5.2 节的方法去检查 TCP/IP 协议。

验证系统是否正常,可以按这个顺序走一遍手工用例:登录管理员账号 -> 办理一个新借书证 -> 入库两本新书 -> 用书名关键字查到其中一本 -> 借出这本书 -> 确认可借数量减一 -> 归还 -> 确认数量恢复。这套流程覆盖了全部核心功能,走通一遍就可以放心用了。

最后把源码打包成独立 exe 文件交给其他人使用时,我的打包习惯是这样:

pyinstaller --hidden-import pymssql \ --hidden-import tkinter \ --name LibrarySystem \ --noconsole \ --clean \ ui_main.py

--noconsole让窗口不显示黑色控制台,--clean每次都清掉上次的临时文件。打包完成后把生成的 dist 目录整个拷给别人,如果对方机器上没有 SQL Server,还需要先把数据库文件在他机器上附加好,或者把 SQL Server 装成一个局域网共享实例,程序里把 server 参数改成对应 IP。

这套系统我拆完最深的感受是:数据库驱动和事务处理才是图书管理系统的关键,界面反而是次要的。很多人花大把时间调按钮布局,结果借书时库存负数都没发现,答辩翻车。从那以后,我每次拿到这类带数据库的资源,都会强制自己先写一遍核心业务的增删改查流程再做界面,这个顺序能让后面所有工作都顺手很多。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询