📌阅读提示:本文主要面向库管与台账业务人员,包含Python语法、安装和使用Pycharm和Python.exe的讲解。如果您没有库存相关业务背景,部分业务案例不容易看懂。
直击痛点:库存数据不同步、对不上?
当新手和库管在库存管理系统中进行商品出入库等操作时,常常遇到系统库存与实际库存不一致、库存对不上的问题——例如系统中某商品库存显示为5,而实际库存只有3。这种差异容易引发超卖、退货流程繁琐,甚至出现仓库里明明有货,却因系统显示无货而始终卖不出去的情况。
面对这些困境,新手和库管想:这真的太麻烦且苦不堪言!明明某商品已经全部售出,却有人反馈库里还有货;明明系统显示有库存,实际却卖不出去,还得填写退货单。库存总是对不上,对账更是让人崩溃。我实在不忍心看着他们如此煎熬,真心想写一个Python脚本来帮他们解决库存对不上的问题。
经过几天的努力,我终于用while循环写出了库存数据自动化同步脚本。在反复调试、不断纠错的过程中,我越改越觉得有意思。如今脚本不仅能成功运行,还切实解决了新手和库管库存对不上的难题。
核心原理:一个 while 循环,搞定库存同步崩溃耗时长
本章写的库存数据自动化同步脚本中,有很多地方用到while循环语法。如果你们不会的话,请阅读以下文章。
Python新手在PyCharm写while必踩5坑
为什么写库存数据自动化同步脚本时要用 while 循环?你们知道吗?
因为 while 循环能够反复校验用户可能输错的情况,实现程序持续运行并处理多轮任务。而如果不用 while 循环,改成用 for 循环,就无法反复检验用户输入错误的情况,也不能让程序持续运行以处理多轮任务——因为 for 循环不是无限循环,它只在特定范围内进行循环。
零基础上手:Python 环境一键配置,照着操作就行,不复杂
运行库存数据自动化同步脚本之前,需要做一些准备工作,就像在进行1000米跑步前需要热身一样。具体需要准备的工作是下载 PyCharm 和 Python.exe,并学会使用它们。如果你们不会的话,请参考如下两篇文章。
安装Pycharm+配置python.exe:0基础新手一次成功
如何使用PyCharm?0基础新手必看!七大核心功能+越用越有意思
可以直接运行:库存数据自动化同步系统(复制粘贴修改参数就ok)
代码核心功能拆解(新手/库管看得懂)
实战演示:库存数据自动化同步完整脚本
importpandasaspdimportos# ============================================================================# 程序功能说明(给库管和Python新手):# 这是一个库存核对与出入库调整工具,主要做三件事:# 1. 把"系统里的库存表"和"实际盘点出来的库存表"进行对比,找出不一样的商品# 2. 用实际盘点的数据覆盖系统数据(自动校正)# 3. 根据你的输入进行商品入库(加数量)或出库(减数量)# ============================================================================whileTrue:# while True 表示无限循环,程序会一直运行,直到你输入 q 退出get_system_data=""whileTrue:# input() 会在屏幕上显示括号里的提示文字,然后暂停等你输入内容,按回车确认get_system_data=input("请输入系统库存数据文件路径(按q退出):")# .lower() 把输入的内容全部变成小写字母,这样你输入 Q 或 q 都能识别ifget_system_data.lower()=="q":break# break 表示跳出循环,结束程序# os.path.exists() 检查电脑里是否真的有这个文件,防止输错路径ifnotos.path.exists(get_system_data):print(f"文件'{get_system_data}'不存在,请重新输入!")continue# continue 表示跳过本轮后面所有代码,让你重新输入# .endswith() 检查文件名是否以指定后缀结尾# 这里检查是不是 Excel 文件(.xlsx 是新格式,.xls 是老格式)ifnotget_system_data.lower().endswith(('.xlsx','.xls')):print(f"文件'{get_system_data}'不是Excel格式,请重新输入!")continuebreakifget_system_data.lower()=="q":break# break 表示跳出循环,结束程序get_physical_data=""whileTrue:get_physical_data=input("请输入实际库存数据文件路径(按q退出):")ifget_physical_data.lower()=="q":breakifnotos.path.exists(get_physical_data):print(f"文件'{get_physical_data}'不存在,请重新输入!")continueifnotget_physical_data.lower().endswith(('.xlsx','.xls')):print(f"文件'{get_physical_data}'不是Excel格式,请重新输入!")continuebreakifget_physical_data.lower()=="q":break# 1. 读取双端数据(系统库 vs 实物盘点)# try...except 是 Python 的"试一试,出错不崩溃"机制# 先尝试执行 try 里面的代码,如果报错就执行 except 里面的代码try:# pd.read_excel() 是 pandas 用来读取 Excel 表格的函数# usecols=['商品名称', '商品数量'] 表示只读取"商品名称"(商品编码)和"商品数量"(数量)这两列,其他列忽略system_data=pd.read_excel(get_system_data,usecols=['商品名称','商品数量'])physical_data=pd.read_excel(get_physical_data,usecols=['商品名称','商品数量'])exceptExceptionase:# Exception 是所有其他错误的统称(如文件损坏、被占用等)print(f"读取文件时出错:{e}")print(f"Excel文件格式错误或文件没包含 '商品名称' 和 '商品数量' 列或其他错误!")continue# 2. 按商品名称合并对齐(类似于 Excel 里的 VLOOKUP 功能)# pd.merge() 把两个表格按指定列拼接在一起# on='商品名称' 表示按商品编码进行匹配# how='outer' 表示保留两边所有的商品,即使只在一边出现(这叫"全外连接")# suffixes 给重名的列加后缀,方便区分数据来自哪张表# indicator=True 会自动新增一列"_merge",标记数据来源:# - left_only:只在系统表里有# - right_only:只在实物表里有# - both:两边都有merged=pd.merge(system_data,physical_data,on='商品名称',how='outer',suffixes=('_系统','_实物'),indicator="库存数据来源")# 3. 筛选差异行(数量不等或单边缺失)# .query() 像 SQL 查询一样筛选数据# 条件意思是:系统数量不等于实物数量,或者不是两边都有(即单边缺失)different=merged.query('商品数量_系统 != 商品数量_实物 or 库存数据来源 != "both"')# 4. 输出差异报告# .to_excel() 把筛选出来的差异数据保存成新的 Excel 文件# index=False 表示不保存表格最左边的行序号(0、1、2...)different.to_excel('库存差异报告.xlsx',index=False)# len() 函数计算列表/表格有多少行print(f"核对完成:共{len(merged)}个商品名称,发现{len(different)}处差异")different_count=len(different)ifdifferent_count!=0:# .to_string() 把表格转成字符串显示在屏幕上# col_space=15 设置列宽为15个字符,justify='left' 设置左对齐print(different.to_string(index=False,col_space=15,justify='left'))else:print("库存没有差异,无需调整。")# 5. 自动校正系统库存数据(用实际库存完全覆盖系统库存文件)# pd.ExcelFile() 打开 Excel 文件,可以读取里面有多少个工作表(sheet)source_xlsx=pd.ExcelFile(get_physical_data)# pd.ExcelWriter() 打开一个 Excel 文件准备写入,会覆盖掉原来的内容# 这里把"实际库存文件"的所有工作表原样复制到"系统库存文件"里withpd.ExcelWriter(get_system_data)asw:forsheetinsource_xlsx.sheet_names:pd.read_excel(source_xlsx,sheet_name=sheet).to_excel(w,sheet_name=sheet,index=False)print("根据实际库存数据,已经自动对系统库存数据进行调整。")# ============================================================================# 以下部分为:入库或出库操作(修改库存数量)# ============================================================================# 重新读取两个文件的数据(此时系统库存文件已经被实际库存覆盖)# engine="openpyxl" 指定读取引擎,这是处理 .xlsx 格式最常用的引擎system_data=pd.read_excel(get_system_data,usecols=['商品名称','商品数量'],engine="openpyxl")physical_data=pd.read_excel(get_physical_data,usecols=['商品名称','商品数量'],engine="openpyxl")# 把 DataFrame(pandas 的表格对象)转换成 Python 字典,方便快速查找和修改# zip() 像拉链一样把两个列表配对:商品名称1对应第一行数据,商品名称2对应第二行数据...# to_dict("records") 把表格的每一行转成字典格式,例如:{'商品名称': 'A001', '商品数量': 100}# 最终结构示例:{'A001': {'商品名称': 'A001', '商品数量': 100}, 'A002': {'商品名称': 'A002', '商品数量': 50}}dict_system_data=dict(zip(system_data['商品名称'],system_data.to_dict("records")))dict_physical_data=dict(zip(physical_data['商品名称'],physical_data.to_dict("records")))# 输入要操作的商品名称add_good=input("请输入要入库或者出库的商品名字(按Q或q退出):")ifadd_good.lower()=="q":breakwhileTrue:# 输入数量:正数表示入库(加库存),负数表示出库(减库存)add_inventory_quantity=input("请输入要入库的数量(正数为入库,负数为出库,按Q或q退出):")ifadd_inventory_quantity.lower()=="q":break# 检查输入的数量是否为合法的整数# input() 获取到的内容永远是"字符串"(文字),即使是"123"也是文字,不是数字# 这里用 int() 尝试把它转换成整数,如果输入了字母、小数或符号会报错(ValueError)try:add_inventory_quantity=int(add_inventory_quantity)exceptValueError:print("商品出库数量或商品入库数量必须为数字,且为整数!")continue# 输入非法,跳过本轮后续操作,回到开头重新输入文件路径ifstr(add_inventory_quantity).lower()=="q":break# 如果该商品在系统库存字典中存在,就修改它的数量# 注意:dict_system_data[add_good] 取到的是一个字典,如 {'商品名称': 'A001', '商品数量': 100}# 所以需要用 ['商品数量'] 才能访问到具体的数量,并进行加减ifadd_goodindict_system_data:dict_system_data[add_good]["商品数量"]+=add_inventory_quantity# 如果该商品在实际库存字典中存在,同样修改数量ifadd_goodindict_physical_data:dict_physical_data[add_good]["商品数量"]+=add_inventory_quantity# 把修改后的字典转换回 DataFrame 表格,再保存为 Excel 文件# dict.values() 取出字典里所有的值(也就是一行行的 {'商品名称': ..., '商品数量': ...})# list() 把这些值转成列表,pd.DataFrame() 再把列表变回表格save_system_data=pd.DataFrame(list(dict_system_data.values()))# 保存到当前文件夹下的 system_inventory.xlsx# engine="openpyxl" 指定保存引擎,确保能正确写入 .xlsx 文件save_system_data.to_excel(get_system_data,index=False,engine="openpyxl")save_physical_data=pd.DataFrame(list(dict_physical_data.values()))save_physical_data.to_excel(get_physical_data,index=False,engine="openpyxl")breakifstr(add_inventory_quantity).lower()=="q":break# 询问是否继续核对其他文件continue_check=input("是否继续核对其他文件?(Y/N):")# 这里统一转成小写再比较,所以输入 Y、y、N、n 都能识别ifcontinue_check.lower()=='n':break# 输入 N,结束程序elifcontinue_check.lower()=='y':continue# 输入 Y,继续下一轮循环else:print("请输入Y或N。")continue# 输入了其他内容,提示错误并继续下一轮运行效果展示
以下这幅图左侧画红框的是我运行库存数据自动化同步脚本时所使用的文件。你们运行此库存数据自动化同步脚本时,可以使用你们自己的文件来试试。
以下这幅图是在系统库存数据和实际库存数据一样的情况下,核对系统库存数据和实际库存数据、系统库存数据自动根据实际库存数据修正、对系统库存数据和实际库存数据进行出入库操作的正确截图。
以下这幅图是对要加载的系统库存数据文件进行检验,主要检验它存不存在以及它是不是Excel格式的。
以下这幅图是对要加载的实际库存数据文件进行检验,主要检验它存不存在以及它是不是Excel格式的。
以下这幅图是对输入完的系统库存数据文件和实际库存数据文件的检验,主要检验它俩是否有Excel文件格式错误、他俩是否包含商品名称和商品数量、他俩是否有其他错误。
以下这幅图是测试对系统库存数据和实际库存数据进行出入库时,输入出入库数量时,按Q或q退出的功能是否正常。
以下这幅图是测试对系统库存数据和实际库存数据进行出入库时,输入要出入库的商品名时,按Q或q退出的功能是否正常。
以下这幅图是在系统库存数据和实际库存数据不一样的情况下,核对系统库存数据和实际库存数据、系统库存数据自动根据实际库存数据修正、对系统库存数据和实际库存数据进行出入库操作及其对出入库数据进行检验的正确截图。
总结:这套脚本能解决什么痛点
在本章中,我用 while 循环写了一个库存数据自动化同步脚本,并附上了核心功能拆解(用流程图表示)、源码和运行结果,你们可以直接复制到 PyCharm 中运行。
这个脚本解决了库存管理系统中的库存数据与实际库存数据不同步、对不上的问题,也解决了 Python 新手和库管人员的一大心病。你们可以根据自己的实际情况,对这个脚本进行复制、修改和运行使用。
Python 新手和库管朋友们,你们能读到这里,说明你们真的迫切想要用这个脚本来解决系统库存与实物库存不同步、对不上的问题——你们真的挺棒、挺了不起的!
你们已经超过了那些还在手工核对系统库存数据与实物库存数据、并且长期被库存数据不同步对不上的问题困扰的人。
我写这个库存数据自动化同步脚本,就是为了送给那些想靠技术翻身的你们——让你们能够用技术,去解决实际生活和工作中的难题。
专栏下篇预告
本专栏的下篇文章,将介绍如何利用 Python 函数语法知识来解决库存管理中的痛点,届时敬请期待!
如果这篇文章对你们的帮助极大,或者说你们喜欢读这篇文章,那么不妨动动你们宝贵的金手指,点赞、收藏、关注,并转发给你们的家人朋友。
持续关注我,我会为你们发布更多内容:Python 语法技巧、Python 实战解决痛点、编程避坑指南、开发工具安装使用教程。
如果你们对我写的文章有疑问和想法,欢迎到评论区留言,我看到后会一一回复。
配套资源:完整源码(附使用说明)下载
本章文末提供完整的单机版库存管理系统脚本,可直接免费下载,下载后可直接在 PyCharm 中运行。你们可以根据实际业务情况,对该脚本进行复制、修改和运行使用。
Python+Tkinter+SQLite 单机版商品库存管理系统源码