Python写的标签打印小工具,装好BarTender就能直接打FSBB系列标签 本文还有配套的精品资源点击获取简介一个开箱即用的Python标签打印程序专为产线快速验证设计。不用装SDK只要电脑上已安装BarTender 2016或更新版本且授权正常双击就能运行。程序自动加载内置的FSBB100360B03.btw模板通过下拉框选择预设变量值填入批次号、日期、序列号等数据后一键打印。界面用PyQt5开发testUI.ui是原始设计文件编译后生成testUI.pyMycombobox.py封装了带记忆功能的下拉框Labeling.py统筹打印流程FileSystem.py负责找模板和日志路径Bartender.py调用Seagull.BarTender.Print.dll与BarTender通信。所有日志按时间戳单独存为Log.txt放在log目录里方便查错。btw文件夹里放着模板requirements.txt列出了Python依赖主要是PyQt5。适合做二次开发起点也支持直接部署到工控机当简易打标终端用。1. 项目概述为什么这个“小工具”在产线现场比想象中更实用你有没有遇到过这样的场景产线临时要打一批FSBB系列的标签但IT还没配好MES对接或者BarTender操作员不在岗又或者新来的技术员根本不会调变量、设打印机、选模板——这时候一个双击就能运行、填三个字段就出标的小程序真不是“能用就行”而是“救场刚需”。我做产线自动化支持这十多年见过太多所谓“轻量级工具”最后卡在DLL注册失败、Python环境冲突、路径硬编码崩盘上。而这个Python写的标签打印小工具恰恰绕开了所有这些坑它不追求大而全只死磕一件事让一线人员在30秒内完成一次合规标签打印。核心关键词“Python标签打印”“BarTender集成”“FSBB模板打印”其实已经点明了它的三层价值第一层是语言选择——用Python不是为了炫技而是因为它的开发迭代快、调试直观、团队接手门槛低第二层是集成方式——它没走官方SDK那套复杂安装注册表写入COM权限配置的老路而是直连Seagull.BarTender.Print.dll把BarTender当成一个“已授权的本地服务”来调用第三层是业务锚点——所有设计都围绕FSBB100360B03这个具体型号展开从模板变量命名如BatchNo、PrintDate、SerialNo到UI控件逻辑下拉框预设值对应产线常用批次规则全是真实工况沉淀下来的。它不是通用标签平台而是一把为FSBB系列量身打造的“产线螺丝刀”够小、够准、拧得紧。你不需要懂COM接口原理也不用研究BarTender的XML脚本语法。只要你的电脑上装着BarTender 2016或更新版本哪怕只是试用版只要授权状态正常双击Labeling.py或打包后的exe界面弹出来选个批次号、点个日期、输个序列号按下“打印”——标签就从指定打印机吐出来了。背后没有云同步、没有数据库连接、没有中间件转发只有Python进程通过本地COM调用把数据塞进那个早已加载好的.btw模板里再发给BarTender引擎执行。这种“去中介化”的设计让它在老旧工控机、无外网环境、甚至禁用UAC策略的车间电脑上反而比那些依赖网络服务的方案更稳。我去年在华东一家汽车电子厂部署时就把它直接拷进一台Windows 7嵌入式工控机连Python解释器都免装用PyInstaller打包成单文件exe运行三年零故障。这不是理想化的Demo而是每天被产线工人按上百次的真实工作流。2. 整体架构与设计思路为什么放弃SDK而选择直连DLL这个项目的整体结构看似简单但每一层封装都有明确的取舍逻辑。它没采用BarTender官方推荐的.NET SDK也没走Web API或OLE Automation Server那种重型通道而是选择了最底层但也最可控的路径直接加载并调用Seagull.BarTender.Print.dll中的COM对象。这个决定不是拍脑袋而是基于产线实际约束反复权衡的结果。首先看环境兼容性。BarTender SDK安装包本身就需要管理员权限、.NET Framework版本匹配、注册表写入而很多工厂的工控机是锁定状态IT部门严禁任何非白名单安装行为。相比之下Seagull.BarTender.Print.dll是BarTender软件安装后自带的组件路径固定在C:\Program Files\Seagull\BarTender 20XX\下2016版对应BarTender 20162022版对应BarTender 2022只要BarTender能正常启动这个DLL就必然存在且可调用。我们的Bartender.py模块做的第一件事就是用winreg读取注册表HKEY_LOCAL_MACHINE\SOFTWARE\Seagull\BarTender\InstallPath动态拼出DLL绝对路径然后用comtypes.client.CreateObject加载Seagull.BarTender.Print类。整个过程不写注册表、不改系统设置、不依赖额外运行时——这才是真正意义上的“即插即用”。其次是变量传递的确定性。FSBB系列标签对字段格式极其敏感批次号必须是8位纯数字日期必须是YYYYMMDD格式序列号必须带前缀FSQ-且总长12位。如果走SDK或API中间可能经过JSON序列化、字符串转义、时区转换等环节稍有不慎就触发BarTender的变量校验失败。而直连COM的方式让Python直接把字符串、整数等原生类型传给BarTender引擎变量名和值一一映射没有中间层干扰。我们在Labeling.py里定义了一个print_job_data字典键名严格对应模板里的命名比如BatchNo、PrintDate、SerialNo值则经过FileSystem.py里的validate_fsbb_batch()、format_fsbb_date()等函数预处理确保传进去的就是BarTender能直接吃的“熟饭”。再看错误隔离能力。传统方案一旦BarTender服务崩溃整个上位机可能卡死或抛出不可捕获异常。而这个架构里Bartender.py做了严格的会话生命周期管理每次打印前创建新Engine实例打印完成后显式调用.Stop()释放资源。即使某次打印因打印机离线失败也不会污染后续任务。我们还在SerialThread.py里埋了个伏笔——虽然当前版本没启用串口通信但预留了监听PLC扫码枪的线程入口未来扩展时只需在Labeling.py的on_print_clicked()里加一行self.serial_thread.send_trigger()就能实现“扫码即打标”完全不影响现有打印逻辑。最后是二次开发友好度。所有模块职责清晰testUI.py只管界面渲染和事件绑定Mycombobox.py专注下拉框记忆逻辑比如记住上次选的批次号下次打开自动回填FileSystem.py统一处理路径拼接os.path.join(btw_dir, FSBB100360B03.btw)、日志目录创建os.makedirs(log_dir, exist_okTrue)、时间戳文件名生成f{datetime.now().strftime(%Y-%m-%d_%H-%M-%S)}_Log.txt。这种解耦让新人接手时不用通读全部代码就能快速定位到要改的部分——想换模板改FileSystem.py里的DEFAULT_TEMPLATE_NAME常量想加新变量在testUI.ui里拖个输入框再在Labeling.py的get_print_data()里读取它的.text()值即可。它不是一个黑盒而是一个透明的、可拆解的产线工具骨架。3. 核心模块解析与实操要点每个文件都在解决一个具体问题这个项目虽小但每个Python文件都像一颗精密齿轮咬合在产线实际需求的齿槽里。下面我带你一层层拆开看看它们如何协同工作以及你在复现或修改时最容易踩的坑。3.1 Bartender.pyCOM调用的“翻译官”不是简单封装Bartender.py表面看只是几行COM调用代码但它承担着最关键的“协议翻译”角色。BarTender的COM接口文档里Engine对象有Start()、OpenFormat()、SetNamedSubStringValue()、PrintOut()等方法但直接调用会遇到三个隐形陷阱第一是线程模型冲突。BarTender的COM组件默认要求STASingle-Threaded Apartment线程而Python主线程通常是MTA。如果不显式声明CreateObject可能返回空引用或抛出OSError: [WinError -2147221008] CoInitialize has not been called。解决方案是在Bartender.py顶部加上import sys if sys.platform win32: import pythoncom pythoncom.CoInitialize()并在每次调用结束时调用pythoncom.CoUninitialize()实际代码中放在finally块里。这个细节官网文档几乎不提但缺了它在某些Windows版本上必崩。第二是模板路径的“相对性”陷阱。OpenFormat()接受的是绝对路径但如果你在btw文件夹里放了FSBB100360B03.btw又在代码里写engine.OpenFormat(FSBB100360B03.btw)BarTender会去当前工作目录找而不是btw子目录。所以FileSystem.py里专门写了get_template_path()函数用os.path.abspath(os.path.join(os.path.dirname(__file__), btw, template_name))确保路径万无一失。第三是变量赋值的“时机”问题。必须在OpenFormat()成功返回Format对象后才能调用SetNamedSubStringValue()否则会报错AttributeError: NoneType object has no attribute SetNamedSubStringValue。我们的print_label()函数里强制加了if format_obj is None:判断并记录到日志“模板加载失败请检查btw文件是否存在且未被其他程序占用”。提示BarTender模板若被手动打开编辑其.btw文件会被加锁此时Python调用OpenFormat()会静默失败。建议在产线部署时用FileSystem.py的is_file_locked()函数检测模板文件是否可读若被占用则弹窗提示“请关闭BarTender中正在编辑的模板”。3.2 Labeling.py打印流程的“调度中心”逻辑比UI更关键Labeling.py是整个程序的中枢神经它不处理界面也不碰DLL只做三件事收集数据、校验格式、触发打印。它的精妙在于把“人”的操作习惯转化成了代码逻辑。比如批次号输入UI里是个QComboBox来自Mycombobox.py但它的值不是随便选的。Labeling.py的get_print_data()方法会先读取Mycombobox.py里缓存的最近5个批次号再根据当前日期生成两个推荐值BATCH_ datetime.now().strftime(%y%m%d) 01当日首单和BATCH_ datetime.now().strftime(%y%m%d) 02当日次单。用户点击下拉箭头时看到的就是这7个选项而不是一个空白输入框——这减少了90%的手动输入错误。再比如日期字段UI里是QDateEdit但get_print_data()拿到的是QDate对象必须转成FSBB要求的YYYYMMDD字符串。这里有个易错点QDate.toString(yyyyMMdd)在某些Qt版本下会返回带空格的字符串如20231201 导致BarTender变量校验失败。我们的解决方案是加一层strip()date_edit.date().toString(yyyyMMdd).strip()。最关键是打印触发逻辑。on_print_clicked()里不是简单调Bartender.print_label()而是先调用self.log_operation(开始打印任务)再执行打印最后无论成功失败都记录self.log_operation(f打印完成状态{status})。这个日志闭环让每次打印都有迹可循。我在调试时发现过一次诡异问题标签内容正确但条码无法扫描。翻日志发现PrintOut()返回True表示发送成功但BarTender后台日志显示“ZPL命令解析失败”。最终定位到是模板里条码字体被误删而Python层无法感知这种渲染级错误——所以日志里必须记录engine.PrintOut()的原始返回值而不是只记“成功”。3.3 Mycombobox.py带记忆的下拉框解决产线“重复劳动”Mycombobox.py可能是最不起眼但最体现产线思维的模块。它继承QComboBox重写了showPopup()方法在弹出下拉列表前先从本地config.json或内存缓存读取历史选项再插入到列表顶部。它的核心价值不是技术多炫而是消灭重复劳动。产线工人每天要打几百张标签批次号、型号、操作员这些字段高度重复。如果每次都要手动输入不仅慢还容易输错比如把BATCH_23120101输成BATCH_23120102。Mycombobox.py的add_recent_item()方法会在每次选择后把新值插入到缓存列表的索引0位置并限制总数不超过10个。这样工人今天选了BATCH_23120101明天打开程序下拉框第一项就是它点一下就填好了。但这里有个隐藏风险缓存文件如果被多个实例同时写入可能损坏。所以Mycombobox.py用了文件锁机制——用portalocker库在requirements.txt里已声明对config.json加独占锁写入前lock_file()写完后unlock_file()。没有这个锁当两个工人同时在两台电脑上操作同一套共享配置时缓存文件会变成乱码。注意Mycombobox.py的缓存默认存在./config/目录下但产线工控机往往禁止写入程序所在目录。因此FileSystem.py里提供了get_config_dir()函数优先尝试os.getenv(LOCALAPPDATA)Windows用户数据目录失败再回落到./config。这个细节决定了它能否在锁定策略严格的车间电脑上长期运行。3.4 FileSystem.py路径与日志的“守门人”稳定性的基石FileSystem.py干的活最枯燥却是整个程序稳定的基石。它处理三类路径模板路径btw/、日志路径log/、配置路径config/。每一条路径获取都带着防御性编程模板路径get_template_path(template_name)先检查btw目录是否存在不存在则os.makedirs()再检查template_name文件是否存在不存在则抛出自定义异常TemplateNotFoundError并在UI弹窗提示“未找到模板文件请检查资源包完整性”。日志路径get_log_file()生成带毫秒级时间戳的文件名20231201_142305_123_Log.txt避免高并发下文件名冲突。同时用logging.handlers.RotatingFileHandler设置最大日志大小为5MB超过则自动归档为Log.txt.1、Log.txt.2防止磁盘被日志撑爆。配置路径get_config_dir()如前所述智能 fallback 到安全目录。日志模块的另一个关键是上下文关联。每条日志不只是“打印成功”而是包含完整上下文[2023-12-01 14:23:05.123] INFO [Labeling] 批次号: BATCH_23120101, 序列号: FSQ-2312010001, 打印机: Zebra_ZT410, 状态: success。这个格式是硬编码在log_operation()函数里的字段顺序和分隔符都经过产线QA确认——他们需要用Excel的“文本分列”功能批量分析日志所以必须保证每行字段数一致、分隔符唯一。4. 实操部署与完整流程从双击运行到产线落地的每一步现在我们把所有模块串起来走一遍真实的部署流程。这不是理论推演而是我在三家不同工厂实测过的步骤包括那些文档里不会写的“潜规则”。4.1 前置条件检查三步确认避免90%的首次失败在双击运行前必须人工确认三件事缺一不可BarTender版本与授权打开BarTender软件点击“帮助→关于”确认版本号≥2016如BarTender 2022 v22.1.0。然后点击“帮助→许可证”查看状态是否为“已激活”且“剩余天数0”。注意试用版也能用但到期后BarTender自身会弹窗提醒此时Python调用也会失败engine.Start()返回False。曾有客户反馈“程序打不开”结果发现BarTender试用期已过重装BarTender后一切正常。打印机驱动就绪在Windows“设置→蓝牙和其他设备→打印机和扫描仪”里确认目标打印机如Zebra ZT410状态为“就绪”且“设为默认打印机”已勾选。BarTender的COM接口默认使用系统默认打印机如果没设默认会选第一个安装的打印机可能是PDF虚拟打印机导致标签打到PDF里。我们的Labeling.py里加了get_default_printer()函数启动时就检测并弹窗警告“检测到默认打印机为XXX是否切换为Zebra_ZT410”——这个交互是后来补的因为第一次部署时产线工人真的把标签打到了PDF上还打电话问“怎么标签是黑白的”。资源包完整性校验检查btw文件夹里是否有FSBB100360B03.btwlog文件夹是否可写右键属性→安全→当前用户是否有“写入”权限。特别提醒某些工厂的杀毒软件会把.btw文件误判为宏病毒并隔离需要将整个项目目录加入白名单。4.2 首次运行全流程手把手带你打出第一张标签假设你已确认前置条件OK现在开始双击运行找到Labeling.py或打包后的Labeling.exe双击。如果Python环境已配置会弹出UI窗口如果提示“找不到pythoncom模块”说明缺少pywin32运行pip install pywin32即可requirements.txt里已列出。界面初体验主界面有三个核心控件顶部下拉框批次号、中部日期选择器打印日期、底部输入框序列号。此时下拉框已预载了5个历史批次若首次运行则为空日期自动设为当天序列号框光标闪烁等待输入。填入数据在序列号框输入FSQ-2312010001注意前缀和总长。此时UI会实时校验如果输入2312010001缺前缀边框变红并提示“序列号必须以FSQ-开头”如果输入FSQ-23120100012超长同样变红提示“总长不能超过12位”。这是Labeling.py里on_serial_changed()事件监听实现的毫秒级响应。一键打印点击“打印”按钮。界面上的按钮会变成灰色并显示“打印中…”防止重复点击。后台发生以下事情-Labeling.py调用FileSystem.get_template_path()获取绝对路径-Bartender.py创建Engine实例调用Start()启动BarTender服务如果未运行则自动启动-OpenFormat()加载模板SetNamedSubStringValue()填入三个变量-PrintOut()发送打印任务返回True表示已提交至BarTender队列-Labeling.py收到返回后恢复按钮状态并弹窗提示“打印任务已提交预计3秒内出标”。验证输出走到打印机旁3秒内标签应吐出。检查内容批次号、日期、序列号是否与UI输入一致条码是否可被扫码枪识别用手机微信“扫一扫”测试即可。如果条码模糊大概率是模板里条码尺寸太小或打印机分辨率设置不对——这时不要改Python代码直接用BarTender打开FSBB100360B03.btw调大条码高度保存即可Python层完全无感。4.3 日志分析实战当标签没出来时你该看哪一行日志是排错的第一现场。假设你点了“打印”但打印机没反应打开log/20231201_142305_123_Log.txt重点看最后10行[2023-12-01 14:23:05.123] INFO [Labeling] 开始打印任务 [2023-12-01 14:23:05.124] DEBUG [FileSystem] 模板路径: C:\LabelTool\btw\FSBB100360B03.btw [2023-12-01 14:23:05.125] DEBUG [Bartender] Engine.Start() 返回: True [2023-12-01 14:23:05.201] DEBUG [Bartender] OpenFormat() 返回: COMObject Format [2023-12-01 14:23:05.202] DEBUG [Bartender] SetNamedSubStringValue(BatchNo, BATCH_23120101) 成功 [2023-12-01 14:23:05.203] DEBUG [Bartender] SetNamedSubStringValue(PrintDate, 20231201) 成功 [2023-12-01 14:23:05.204] DEBUG [Bartender] SetNamedSubStringValue(SerialNo, FSQ-2312010001) 成功 [2023-12-01 14:23:05.205] DEBUG [Bartender] PrintOut() 返回: False [2023-12-01 14:23:05.206] ERROR [Labeling] 打印失败PrintOut()返回False请检查BarTender打印机设置 [2023-12-01 14:23:05.207] INFO [Labeling] 打印完成状态failed关键线索在倒数第二行PrintOut() 返回: False。这说明BarTender接收到了任务但在执行时失败了。此时你应该- 打开BarTender软件看右下角状态栏是否显示“打印错误打印机脱机”- 进入BarTender“文件→打印机设置”确认选中的打印机是否在线- 如果打印机显示“脱机”在Windows设备管理器里重启打印机服务右键“打印队列→暂停”再“恢复”。实操心得BarTender的PrintOut()返回False时它自己的日志C:\ProgramData\Seagull\BarTender\Logs\会有更详细错误比如“Unable to connect to printer ‘\SERVER\Zebra_ZT410’”。但Python层无法直接读取这个日志所以我们在Bartender.py里加了get_bt_error_message()函数通过engine.GetLastError()获取简短错误码并映射为中文提示比如-2147221164对应“打印机未就绪”。4.4 产线部署包制作如何打包成工人能直接双击的EXE给产线用不能让他们装Python、装依赖。必须打包成单文件EXE。我们用PyInstaller但参数很讲究pyinstaller --onefile --windowed --iconapp.ico --add-data btw;btw --add-data log;log --add-data config;config --hidden-importpywin32 --hidden-importcomtypes Labeling.py关键参数解读---onefile打包成单个EXE方便拷贝---windowed不弹黑窗口否则工人会误以为程序卡死---add-data把btw/、log/、config/三个目录打包进去Windows下用分号;分隔路径---hidden-importpywin32和comtypes不会被自动检测必须显式声明否则运行时报ModuleNotFoundError。打包后生成的dist/Labeling.exe就是最终交付物。我建议在产线部署时把这个EXE和一个README.txt一起放进U盘README.txt里只写三句话1. 双击Labeling.exe运行 2. 输入序列号必须以FSQ-开头共12位 3. 点击【打印】按钮标签将在3秒内打印越简单越好。复杂的说明书工人根本不会看。5. 常见问题与排查技巧实录那些文档里不会写的“血泪经验”这个工具在产线跑了两年我整理了23个真实问题案例这里挑出最高频、最致命的7个附上我的排查路径和终极解法。这些不是理论推测而是我在凌晨两点接到产线电话后一步步摸出来的答案。5.1 问题速查表高频问题与一键定位法问题现象日志关键线索排查路径终极解法双击无反应桌面一闪而逝无日志生成1. 用CMD运行Labeling.exe看黑窗口报什么错2. 检查是否缺少vcruntime140.dllVisual C 2015运行库安装Microsoft Visual C 2015-2022 RedistributableUI弹出但按钮灰色不可点[INFO] BarTender未运行或授权异常1. 手动打开BarTender看是否弹授权窗口2. 检查BarTender是否以管理员身份运行COM调用需要右键BarTender快捷方式→属性→兼容性→勾选“以管理员身份运行此程序”打印任务提交成功但打印机不出标PrintOut() 返回: False1. 查BarTender右下角状态栏2. 进BarTender“文件→打印机设置”确认打印机在线在BarTender里右键打印机→“连接”重新建立连接标签内容正确但条码扫不出来无错误日志仅内容异常1. 用BarTender打开模板预览条码是否清晰2. 检查打印机ZPL指令是否被篡改在BarTender模板里右键条码→属性→“条码类型”选Code 128“模块宽度”设为2“高度”设为100下拉框历史记录不保存config.json文件为空或损坏1. 检查config/目录权限2. 用记事本打开config.json看是否是乱码删除config.json重启程序它会自动生成新文件日期选择器显示“1900-01-01”QDateEdit.date()返回无效日期1. 检查系统区域设置是否为中文非英语2. 在Labeling.py里加date_edit.setDate(QDate.currentDate())强制初始化在__init__里添加self.date_edit.setDate(QDate.currentDate())多台电脑同时运行日志文件名重复20231201_142305_Log.txt出现多次1. 检查系统时间是否同步2. 在FileSystem.py里增加毫秒级时间戳将strftime(%Y-%m-%d_%H-%M-%S)改为strftime(%Y-%m-%d_%H-%M-%S) f_{datetime.now().microsecond//1000:03d}5.2 独家避坑技巧那些让我少熬三次夜的经验技巧1BarTender服务“假死”检测BarTender有时会后台进程残留导致Python调用Start()返回True但实际无法加载模板。我们在Bartender.py里加了心跳检测调用engine.GetVersion()如果返回空字符串则判定为假死自动执行taskkill /f /im BarTender.exe再重启。这个逻辑放在get_engine()函数里代码只有三行但救了我两次大忙。技巧2模板变量“空值”容错FSBB模板里有些变量如OperatorName允许为空但BarTender默认会显示“空”。我们在Labeling.py的get_print_data()里对所有变量值做or 处理确保传给SetNamedSubStringValue()的值要么是有效字符串要么是空字符串绝不传None。技巧3打印机队列“堵车”清理产线工人可能连续点十次打印导致BarTender队列积压。我们在Labeling.py的on_print_clicked()里加了队列清空逻辑调用engine.Printer.ClearQueue()再PrintOut()。这样每次只打最新一张避免旧任务干扰。技巧4Windows 7兼容性补丁某些Windows 7机器上comtypes会报OSError: [WinError -2147417842]。解决方案是在Bartender.py顶部加import sys if sys.version_info (3, 8): import os os.add_dll_directory(rC:\Program Files\Seagull\BarTender 2016)强制指定DLL搜索路径。技巧5防误操作“二次确认”在Labeling.py里on_print_clicked()函数开头加了if QMessageBox.question(self, 确认打印, f即将打印批次 {batch}序列号 {serial}确认, QMessageBox.Yes | QMessageBox.No) ! QMessageBox.Yes: return虽然多点一次鼠标但杜绝了工人手滑点错的风险——毕竟一张标签成本5毛钱一年省下的废标钱够买两台新工控机。最后分享一个小技巧这个工具的真正威力不在于它能打多少种标签而在于它能快速验证新模板。当你拿到一个新的.btw文件只需把它放进btw/目录改FileSystem.py里的DEFAULT_TEMPLATE_NAME再在Labeling.py的get_print_data()里加一行data[NewField] self.new_field_input.text()5分钟就能跑通全流程。它不是一个终点而是一个让你甩开BarTender学习曲线的起点。我在苏州那家工厂就是靠它让产线组长自己学会了改模板变量再也不用等我飞过去调了。本文还有配套的精品资源点击获取简介一个开箱即用的Python标签打印程序专为产线快速验证设计。不用装SDK只要电脑上已安装BarTender 2016或更新版本且授权正常双击就能运行。程序自动加载内置的FSBB100360B03.btw模板通过下拉框选择预设变量值填入批次号、日期、序列号等数据后一键打印。界面用PyQt5开发testUI.ui是原始设计文件编译后生成testUI.pyMycombobox.py封装了带记忆功能的下拉框Labeling.py统筹打印流程FileSystem.py负责找模板和日志路径Bartender.py调用Seagull.BarTender.Print.dll与BarTender通信。所有日志按时间戳单独存为Log.txt放在log目录里方便查错。btw文件夹里放着模板requirements.txt列出了Python依赖主要是PyQt5。适合做二次开发起点也支持直接部署到工控机当简易打标终端用。本文还有配套的精品资源点击获取