用Python实现可靠库存管理系统:AI工作流与事务校验实战
发布时间:2026/9/3 7:49:24 作者:尧图编辑部 阅读量:1,286

很多同学在使用 AI 工作流工具时都会尝试说一句话让工具生成一个系统比如“帮我写一个商品库存管理系统”。代码确实能很快产出但真正落地时问题不少SKU 重复怎么办出库数量大于库存怎么办数据重启后会不会丢多条流水怎么追溯这些问题AI 工具只能帮你搭框架真正要让系统可靠运行还是需要理解 Python 的数据结构、异常处理和持久化方式。这篇文章就以 WorkBuddy 这类 AI 工具为辅助入口以 Python 作为核心实现语言逐步完成一个可以被真实使用的商品库存管理系统。全文会从需求拆解、环境准备、数据模型设计、核心代码编写到命令行交互和常见问题排查完整走一遍。即使你之前没有用过 WorkBuddy也不影响阅读本项目的核心能力完全由 Python 实现WorkBuddy 在其中扮演的是需求分析和代码辅助生成的角色。1. 项目背景与整体思路1.1 一句话需求背后缺什么“商品库存管理系统”这句话看起来很具体但实际上它包含了许多隐藏需求。我们需要先问自己几个问题。库存系统是给谁用的是仓库管理员、门店店员还是后端接口调用方商品有哪些字段至少需要 SKU、名称、分类、单价、数量、安全库存。库存变化是否需要记录流水只记录当前库存还是每次入库、出库、盘点都要留痕数据存储方式是什么先落地成本地文件还是直接上数据库出库时库存不足是拦截还是允许负库存这些需求不明确AI 生成的代码就会飘忽不定。很多 AI 工具生成的第一版库存系统往往只是把商品信息放进一个列表程序一关闭数据就全部丢失连最基本的持久化都没有。因此我们在向 WorkBuddy 描述需求时必须把功能边界说清楚然后用自己的 Python 知识把关键逻辑加固。1.2 WorkBuddy 与 Python 的搭配方式WorkBuddy 这类工具擅长的是把自然语言需求转成任务清单再辅助生成代码、脚本或业务流。它就像一个“需求翻译器 代码生成器”但我们不能把它输出的代码当成最终结果直接上线。在我建议的工作流中WorkBuddy 承担三个职责。需求拆解将一句话需求展开成功能模块清单。代码雏形按照模块清单生成第一版 Python 代码。代码审查把运行报错或逻辑问题反馈给它让它给出修改建议。Python 承担的是真正的实现职责定义商品数据结构、处理文件读写、校验输入合法性、维护出入库流水、提供命令行交互界面。最终代码的质量仍然取决于编写者对 Python 基础知识的掌握程度以及遇到边界条件时能否把问题描述清楚。这样搭配的好处是AI 工具帮助我们缩短从空白文件到第一版代码的时间而我们自己掌握核心算法和数据结构这样可以确保系统经得起真实业务推敲。2. 环境准备与项目结构2.1 安装 Python 环境本项目使用 Python 3 标准库实现不依赖第三方数据库因此环境准备非常简单。操作系统Windows 10/11、macOS 或 Linux 均可。Python 版本建议 Python 3.8 或更高版本。开发工具VS Code、PyCharm或者直接使用系统终端。命令行工具能执行 python 命令即可。在终端中执行以下命令确认 Python 环境正常。python --version如果你使用的是 Windows 系统可能需要将命令换成py --version或python3 --version具体取决于安装时是否勾选了环境变量。只要能看到类似Python 3.10.x的输出就说明环境可用了。2.2 创建项目结构为了让代码层次清晰我们新建一个目录专门存放库存系统相关文件。inventory_system/ ├── inventory.py # 库存业务核心逻辑 ├── main.py # 命令行交互入口 └── data/ # 程序运行时自动生成的数据目录其中inventory.py负责商品和流水的数据管理main.py负责与用户交互data目录用来存放 JSON 数据文件。这样的拆分可以让业务逻辑与界面逻辑解耦便于后续将命令行界面替换成 Flask Web 接口或 PyQt 桌面界面。2.3 明确功能边界在编写代码之前需要先把系统功能限制在一个清晰范围内。本文实现的库存管理系统包含以下功能。新增商品录入 SKU、名称、分类、单价、初始库存、安全库存。商品入库指定 SKU 和数量增加库存并记录流水。商品出库指定 SKU 和数量减少库存并记录流水。库存盘点直接修正库存数量生成盘点调整流水。库存查询按 SKU 查询单个商品。商品列表查看所有商品。低库存预警当当前库存小于等于安全库存阈值时给出提示。流水追溯查看所有库存变化记录也可以按 SKU 单独查看。低于安全库存时系统允许继续出库但会通过“低库存预警”功能提醒用户补货。出库数量大于当前库存时系统必须拦截不允许把库存扣成负数这是库存系统的核心红线。3. 库存管理系统的核心设计3.1 商品数据模型商品表是整个系统的基础每个商品都应有一个唯一标识。最常用的唯一标识是 SKU也就是“库存量单位”。同一个商品名称可能对应多个 SKU比如不同颜色、不同规格的商品必须分开管理。本文中每个商品使用一个字典表示字段如下。字段类型说明skustr商品唯一编码不可重复namestr商品名称categorystr商品分类pricefloat商品单价单位元quantityint当前库存数量safety_stockint安全库存阈值例如一个无线鼠标的商品数据可以表示成这样。{ sku: A001, name: 无线鼠标, category: 办公外设, price: 59.9, quantity: 100, safety_stock: 20 }如果后续要扩展系统例如增加商品规格、供应商、存放仓库等字段只需要在商品字典中追加键即可。但要注意追加字段后旧的 JSON 数据文件可能缺少新字段读取时需要做空值兼容处理。3.2 流水记录为什么重要只保存当前库存数量无法回答“这批货是什么时候进来的”或者“库存为什么少了”这类问题。为了保证可追溯性库存系统必须记录每一笔变动流水。每次入库、出库、盘点调整都应该写入一条流水记录。流水记录至少包含以下字段。字段说明time操作时间sku操作的商品编码type操作类型IN 为入库OUT 为出库ADJUST 为盘点调整quantity变动数量调整可以为负数note备注信息这种设计在软件开发中叫作“事件溯源”思想。库存的当前值可以通过初始数据和流水计算出来也可以理解为“库存 所有入库 - 所有出库 调整”。即使是本地 JSON 文件的小项目养成记录流水的习惯也非常重要因为未来迁移到数据库时流水表可以直接复用。3.3 库存操作的边界条件库存系统的难点不在正常流程而在异常情况。以下边界条件是 AI 生成代码时最容易遗漏的地方。商品 SKU 已存在时新增商品要报错。入库数量必须大于 0。出库数量必须大于 0。出库数量大于当前库存时必须阻止并发出提示。修改库存时不允许出现负数。单价和库存数量必须是合法数字不能出现“abc”这样的输入。在代码实现时我们可以通过抛出自定义ValueError异常来处理业务错误在交互层统一捕获并显示提示信息。这样核心业务逻辑不会混入大量print代码也会更干净。4. 完整实战从 WorkBuddy 需求到可运行代码4.1 用 WorkBuddy 拆解需求在开始写代码之前可以先试着把需求描述给 WorkBuddy。我这里给出一段可以直接复制使用的需求描述。请作为资深 Python 工程师帮我实现一个商品库存管理系统。要求如下 1. 使用 Python 标准库实现不依赖第三方数据库。 2. 数据持久化到本地 JSON 文件编码格式为 UTF-8。 3. 商品字段包含 SKU、名称、分类、单价、当前库存、安全库存阈值。 4. 支持新增商品、商品入库、商品出库、库存盘点、库存查询、低库存预警、流水查询。 5. 库存量不能为负数出库前必须校验库存是否充足。 6. 每次入库、出库、盘点调整都要记录流水字段包含时间、SKU、操作类型、数量、备注。 7. 采用面向对象方式将库存核心逻辑封装为 InventoryManager 类。 8. 提供命令行交互菜单方便本地测试。WorkBuddy 收到需求后通常会返回一个代码雏形。这个雏形可能有以下问题没有做 SKU 重复校验没有处理 JSON 文件不存在的情况出库逻辑缺少库存检查。我们需要带着这些预期使用自己的 Python 能力去修正和完善代码。接下来我会直接给出一个相对完整且可运行的版本。4.2 编写数据持久化模块 inventory.py在项目目录下创建inventory.py文件完整代码如下。# 文件路径inventory_system/inventory.py import json import os from datetime import datetime DATA_DIR data PRODUCTS_FILE os.path.join(DATA_DIR, products.json) TRANSACTIONS_FILE os.path.join(DATA_DIR, transactions.json) def _ensure_data_files(): 初始化数据目录和 JSON 文件。 os.makedirs(DATA_DIR, exist_okTrue) if not os.path.exists(PRODUCTS_FILE): with open(PRODUCTS_FILE, w, encodingutf-8) as f: json.dump([], f, ensure_asciiFalse, indent2) if not os.path.exists(TRANSACTIONS_FILE): with open(TRANSACTIONS_FILE, w, encodingutf-8) as f: json.dump([], f, ensure_asciiFalse, indent2) def _load_json(path): 读取 JSON 文件。 with open(path, r, encodingutf-8) as f: return json.load(f) def _save_json(path, data): 写入 JSON 文件。 with open(path, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse, indent2) class InventoryManager: 库存管理核心类。 def __init__(self): _ensure_data_files() self.products _load_json(PRODUCTS_FILE) self.transactions _load_json(TRANSACTIONS_FILE) def _save_products(self): _save_json(PRODUCTS_FILE, self.products) def _save_transactions(self): _save_json(TRANSACTIONS_FILE, self.transactions) def _add_transaction(self, sku, op_type, quantity, note): 新增一条库存流水记录。 record { time: datetime.now().isoformat(timespecseconds), sku: sku, type: op_type, quantity: quantity, note: note, } self.transactions.append(record) self._save_transactions() def _find_product(self, sku): 根据 SKU 查找商品。 for product in self.products: if product[sku] sku: return product return None def add_product(self, sku, name, category, price, quantity0, safety_stock0): 新增商品。 if self._find_product(sku): raise ValueError(fSKU {sku} 已存在) if price 0: raise ValueError(单价不能为负数) if quantity 0: raise ValueError(初始库存不能为负数) product { sku: sku, name: name, category: category, price: float(price), quantity: int(quantity), safety_stock: int(safety_stock), } self.products.append(product) self._save_products() return product def stock_in(self, sku, quantity, note): 商品入库。 if quantity 0: raise ValueError(入库数量必须大于 0) product self._find_product(sku) if not product: raise ValueError(fSKU {sku} 不存在) product[quantity] quantity self._save_products() self._add_transaction(sku, IN, quantity, note) return product def stock_out(self, sku, quantity, note): 商品出库。 if quantity 0: raise ValueError(出库数量必须大于 0) product self._find_product(sku) if not product: raise ValueError(fSKU {sku} 不存在) if product[quantity] quantity: raise ValueError(库存不足出库失败) product[quantity] - quantity self._save_products() self._add_transaction(sku, OUT, quantity, note) return product def adjust_stock(self, sku, new_quantity, note): 库存盘点调整将库存修正为指定数量。 if new_quantity 0: raise ValueError(盘点后的库存不能为负数) product self._find_product(sku) if not product: raise ValueError(fSKU {sku} 不存在) diff new_quantity - product[quantity] product[quantity] new_quantity self._save_products() self._add_transaction(sku, ADJUST, diff, note f 调整后库存 {new_quantity}) return product def get_product(self, sku): 查询单个商品。 return self._find_product(sku) def list_products(self): 查看全部商品。 return self.products def low_stock_products(self): 低库存预警列表。 low_stock [] for product in self.products: if product[quantity] product[safety_stock]: low_stock.append(product) return low_stock def list_transactions(self, skuNone): 查询流水记录可按 SKU 过滤。 if sku: return [item for item in self.transactions if item[sku] sku] return self.transactions这段代码有几个关键设计点需要理解。_ensure_data_files会在程序启动时自动创建data目录和两个 JSON 文件避免因文件不存在而崩溃。add_product在写入前会判断 SKU 是否重复重复时会抛出ValueError。stock_out在扣减库存之前会判断库存是否足够避免出现负库存。所有写操作都会同步更新内存中的数据并调用_save_json将数据保存到文件。_add_transaction是内部方法不希望被外部直接调用因此以单下划线开头这是 Python 约定俗成的“受保护成员”写法。4.3 编写命令行交互入口 main.py数据层写好后还需要一个命令行交互入口。在项目目录下创建main.py文件完整代码如下。# 文件路径inventory_system/main.py from inventory import InventoryManager TYPE_TEXT { IN: 入库, OUT: 出库, ADJUST: 盘点调整, } def input_float(prompt, min_value0.0): 输入浮点数并校验最小值。 while True: text input(prompt).strip() try: value float(text) if value min_value: print(f输入不能小于 {min_value}请重新输入。) continue return value except ValueError: print(请输入合法的数字。) def input_int(prompt, defaultNone, min_value0): 输入整数支持默认值并校验最小值。 while True: text input(prompt).strip() if text and default is not None: return default try: value int(text) if value min_value: print(f输入不能小于 {min_value}请重新输入。) continue return value except ValueError: print(请输入合法的整数。) def print_product(product): 打印单个商品信息。 print(fSKU{product[sku]}) print(f名称{product[name]}) print(f分类{product[category]}) print(f单价{product[price]:.2f} 元) print(f库存{product[quantity]}) print(f安全库存{product[safety_stock]}) def menu_add_product(manager): 新增商品。 print(\n--- 新增商品 ---) sku input(请输入 SKU商品编码).strip() if manager.get_product(sku): print(新增失败该 SKU 已存在。) return name input(请输入商品名称).strip() category input(请输入商品分类).strip() price input_float(请输入单价元) quantity input_int(请输入初始库存直接回车默认为 0, default0) safety_stock input_int(请输入安全库存阈值直接回车默认为 0, default0) try: manager.add_product(sku, name, category, price, quantity, safety_stock) print(f商品创建成功{sku} {name}当前库存 {quantity}) except ValueError as exc: print(f创建失败{exc}) def menu_stock_in(manager): 商品入库。 print(\n--- 商品入库 ---) sku input(请输入 SKU).strip() product manager.get_product(sku) if not product: print(入库失败商品不存在。) return quantity input_int(请输入入库数量, min_value1) note input(请输入备注直接回车跳过).strip() try: manager.stock_in(sku, quantity, note) print(f入库成功{product[name]} 增加 {quantity}当前库存 {product[quantity]}) except ValueError as exc: print(f入库失败{exc}) def menu_stock_out(manager): 商品出库。 print(\n--- 商品出库 ---) sku input(请输入 SKU).strip() product manager.get_product(sku) if not product: print(出库失败商品不存在。) return quantity input_int(请输入出库数量, min_value1) note input(请输入备注直接回车跳过).strip() try: manager.stock_out(sku, quantity, note) print(f出库成功{product[name]} 减少 {quantity}当前库存 {product[quantity]}) except ValueError as exc: print(f出库失败{exc}) def menu_adjust_stock(manager): 库存盘点调整。 print(\n--- 库存盘点调整 ---) sku input(请输入 SKU).strip() product manager.get_product(sku) if not product: print(调整失败商品不存在。) return print(当前库存, product[quantity]) new_quantity input_int(请输入盘点后的实际库存) note input(请输入盘点备注直接回车跳过).strip() try: manager.adjust_stock(sku, new_quantity, note) print(f调整成功{product[name]} 当前库存 {product[quantity]}) except ValueError as exc: print(f调整失败{exc}) def menu_query_product(manager): 查询单个商品。 print(\n--- 商品查询 ---) sku input(请输入 SKU).strip() product manager.get_product(sku) if not product: print(没有找到该商品。) return print_product(product) def menu_list_products(manager): 查看全部商品。 print(\n--- 全部商品 ---) products manager.list_products() if not products: print(当前没有商品。) return for product in products: print_product(product) print(- * 30) def menu_low_stock(manager): 低库存预警。 print(\n--- 低库存预警 ---) products manager.low_stock_products() if not products: print(暂无低库存商品。) return for product in products: print(fSKU {product[sku]} {product[name]} 当前库存 {product[quantity]}安全库存 {product[safety_stock]}) def menu_transactions(manager): 查看流水记录。 print(\n--- 库存流水 ---) sku input(请输入 SKU 查询流水直接回车查看全部).strip() records manager.list_transactions(sku or None) if not records: print(没有找到相关流水。) return for record in records: type_text TYPE_TEXT.get(record[type], record[type]) print(f{record[time]} | {record[sku]} | {type_text} | 数量 {record[quantity]} | {record[note]}) def main(): 命令行主入口。 manager InventoryManager() while True: print(\n 商品库存管理系统 ) print(1. 新增商品) print(2. 查看全部商品) print(3. 商品入库) print(4. 商品出库) print(5. 库存盘点) print(6. 查询单个商品) print(7. 低库存预警) print(8. 查看库存流水) print(0. 退出系统) choice input(请选择操作).strip() if choice 1: menu_add_product(manager) elif choice 2: menu_list_products(manager) elif choice 3: menu_stock_in(manager) elif choice 4: menu_stock_out(manager) elif choice 5: menu_adjust_stock(manager) elif choice 6: menu_query_product(manager) elif choice 7: menu_low_stock(manager) elif choice 8: menu_transactions(manager) elif choice 0: print(系统已退出。) break else: print(无效选项请重新输入。) if __name__ __main__: main()这段代码相比 AI 直接生成的版本增加了几层保护。输入函数input_float和input_int通过while True循环处理非法输入避免用户输入非数字导致程序崩溃。如果 SKU 不存在菜单函数会直接 return不继续执行后续逻辑。如果 SKU 已存在新增商品会被拒绝防止同一商品编码被重复添加。每个修改操作都包在try except ValueError中把业务错误转成友好的中文提示。4.4 运行与验证在项目目录下执行以下命令启动系统。cd inventory_system python main.py程序启动后会看到主菜单输入对应的数字即可操作。下面是一次完整的测试过程。 商品库存管理系统 1. 新增商品 2. 查看全部商品 3. 商品入库 4. 商品出库 5. 库存盘点 6. 查询单个商品 7. 低库存预警 8. 查看库存流水 0. 退出系统 请选择操作1 请输入 SKU商品编码A001 请输入商品名称无线鼠标 请输入商品分类办公外设 请输入单价元59.9 请输入初始库存直接回车默认为 0 请输入安全库存阈值直接回车默认为 020 商品创建成功A001 无线鼠标当前库存 0接着执行入库操作将数量增加到 100。请选择操作3 请输入 SKUA001 请输入入库数量100 请输入备注直接回车跳过首批采购入库 入库成功无线鼠标 增加 100当前库存 100然后执行出库操作。请选择操作4 请输入 SKUA001 请输入出库数量30 请输入备注直接回车跳过门店调货 出库成功无线鼠标 减少 30当前库存 70如果尝试出库 100 件系统会拦截并提示库存不足不会出现负库存。4.5 数据结果说明程序运行结束后data目录下会自动生成products.json和transactions.json两个文件。products.json中保存的是当前商品列表。[ { sku: A001, name: 无线鼠标, category: 办公外设, price: 59.9, quantity: 70, safety_stock: 20 } ]transactions.json中保存的是流水记录。从流水可以看出A001 商品先入库 100再出库 30当前库存为 70。[ { time: 2025-01-01T10:20:00, sku: A001, type: IN, quantity: 100, note: 首批采购入库 }, { time: 2025-01-01T10:25:00, sku: A001, type: OUT, quantity: 30, note: 门店调货 } ]注意因为stock_out和stock_in在操作时都会调用_save_json所以即使程序中途异常退出已经完成的操作也会保留在 JSON 文件中不会全部丢失。这种设计比只在退出时保存一次更安全。5. 常见问题与排查思路在实际使用过程中最常见的几个问题如下。问题现象常见原因解决思路打开 JSON 文件出现中文乱码写入时没有指定encodingutf-8或缺少ensure_asciiFalse文件读写统一使用encodingutf-8写入 JSON 时加上ensure_asciiFalse重复新增同一 SKU 商品新增逻辑没有做唯一性校验在add_product中先调用_find_product判断 SKU 是否已存在出库后库存变成负数出库逻辑没有校验库存数量扣减库存之前判断product[quantity] quantity时抛出异常程序启动时报 FileNotFoundError数据目录或 JSON 文件不存在使用os.makedirs自动创建目录使用json.dump初始化空列表用户输入非数字导致程序崩溃直接对input结果调用int()或float()而没有异常处理使用循环实现input_int/input_float捕获ValueError后重新输入库存数据丢失只在退出时保存数据用户强制关闭终端导致数据未写入每次变更后立即调用_save_products或_save_transactions这里需要特别说明负库存问题。在真实业务中负库存经常由两种原因导致一是系统逻辑没有校验二是多人同时操作读取到的库存是旧值。本文的 JSON 版本只适合单机学习如果部署到多用户环境则需要换成数据库并配合事务处理。6. 最佳实践与工程建议6.1 数据层升级路线JSON 文件方案最大的优点是简单不需要安装数据库适合学习和演示。但它也有明显瓶颈并发写入容易产生数据冲突数据量变大后查询性能下降文件损坏后恢复困难。当系统需要真正被多人使用时建议把数据层替换为 SQLite 或 MySQL。SQLite适合中小团队内部系统、单机并发量不高的场景Python 标准库自带sqlite3无需额外安装服务。MySQL/PostgreSQL适合需要多人并发、数据可靠性要求更高的生产环境。在升级到数据库时InventoryManager的接口可以保持不变内部把self.products从列表查询改为 SQL 查询把_save_json替换为事务提交。对外层main.py来说调用方式不变改造成本会小很多。有一个细节需要特别提醒出库操作在数据库中应该使用事务和行锁。例如 SQLite 中可以使用BEGIN IMMEDIATEMySQL 中可以使用SELECT ... FOR UPDATE锁定商品行再执行扣减操作避免两个用户同时出库造成超卖。6.2 安全与备份库存数据属于业务数据无论项目大小都应该有备份意识。使用 JSON 文件时定期复制data目录即可完成备份。使用数据库时则需要根据数据库类型执行对应的备份命令。另外不要让程序以管理员权限运行。库存管理系统的命令行版本只监听本地输入风险较低但如果后续改造成 Web 服务并部署到公网必须增加身份认证、操作权限控制、操作日志审计等机制。任何库存调整、删除操作都应该是可追溯的。6.3 AI 生成代码后的检查清单如果你仍然希望更多依赖 WorkBuddy 这类工具来辅助开发下面这份检查清单可以帮助你减少返工。是否校验了用户输入程序中不能出现直接int(input())就转换的情况。是否存在重复数据风险SKU、订单号等唯一字段必须有重复性检查。是否保证业务数据不丢失每次变更后是否立即写盘或提交事务。是否处理了文件路径不存在问题程序第一次运行时依赖目录是否会自动创建。是否考虑了库存负值、金额负值等明显业务错误是否记录了关键操作日志能让问题回溯代码是否模块化业务逻辑与界面逻辑是否分离方便后续替换成 Web 或桌面界面可以在需求描述中把这些检查项直接附在后面让 WorkBuddy 在生成代码时优先考虑。例如补充这样一句“请同时提供单元测试思路并确保所有输入都经过合法校验库存不能为负数。”这能显著提升生成代码的质量。7. 总结与下一步跑完这套流程你会得到一个可用的商品库存管理小系统支持新增商品、入库、出库、盘点调整、库存查询、低库存预警和流水查询所有数据都会持久化到本地 JSON 文件。这个系统虽然简单但包含了真实库存系统的几个关键要素商品主数据、库存变化流水、出入库校验和低库存提醒。很多中型系统本质上就是把这几部分做得更复杂、更安全、更高效。接下来如果你希望继续深入建议按下面的顺序推进。先熟悉 Python 的sqlite3模块把 JSON 数据存储替换为 SQLite 数据库。在出库逻辑中加上事务控制模拟两个终端同时出库观察是否会出现超卖。把命令行入口替换成 Flask Web 接口给商品和库存操作增加 HTTP 接口。给系统增加登录和权限控制区分普通操作员和管理员角色。AI 工具可以让“从一句话到第一版代码”的过程变得很快但库存系统是否能稳定运行仍然取决于你是否理解数据一致性、异常处理和边界校验。建议你拿到代码后先运行一遍完整流程再手动修改几个字段观察异常情况这样才能真正掌握这个系统也为后续接入更复杂的 ERP、订单系统打好基础。