← All posts

2026-10-23

使用 Python 字段脚本自动化标签打印

使用 Python 字段脚本自动化标签打印
pdf labels barcodes label merge browser based graphical layout editor google sheets addin microsoft excel addon electronic shelf labels esl barcode3 labels label editor

使用 Python 字段脚本实现标签打印自动化

标签几乎每次都是对的。日期过期了,序列号丢了前导零,总数需要校验位才能让条码扫描通过。于是有人打开设计器里的标签模板,改三个字段,点击打印,然后第二天早上重复完全相同的事情。

这种编辑不应该放在模板里,而应该放在打印那一刻运行的代码里。RSJ LPSNG 允许你将 Python 脚本块直接附加到标签字段上,因此转换发生在模板内部——没有预处理步骤,不需要在你的 ERP 和打印机之间搞"先修好 CSV"的仪式。

本文讨论的是字段级自动化:什么是字段脚本、如何一次性配置好、如何通过 Web 服务 API 驱动它,以及如何防止它悄悄破坏你的生产线。

另外两个相邻主题在其他文章中有介绍:随订单变化的内容见在标签打印 API 之上构建订单专属标签,来自电子表格的数据驱动标签见如何从 Excel 数据文件和查找表创建标签。本文只聚焦于字段。

为什么用 Python 字段脚本实现标签打印自动化?

字段脚本运行在标签模板内部。Python 块附加到字段上,可以访问该字段的当前值,并在标签渲染之前对其进行修改。这一个设计决策改变了整个流程:

  • 无需外部预处理。 你不需要一个在提交数据之前重写输入数据的脚本。数据原样传入;标签负责修正需要修正的内容。
  • 跨客户端一致性。 脚本随标签一起走。无论作业来自 Web UI、Web 服务 API 还是 LPSNG Player,同一个字段都得到相同的处理。
  • 逻辑可审查。 它就在所影响字段的旁边,而不是在某人笔记本电脑上的 cron 任务里。

值得这样做的任务都是些枯燥重复的事情:

任务 手动方式 字段脚本
打印时间戳 在字段中手动输入今天的日期 在渲染时格式化值
序列号 手动补零,漏掉一个,重新打印 规范化为固定宽度
校验位 在电子表格中计算 从字段值计算
派生标签 从另一个字段复制值 引用源字段

这些都不难。这正是重点——它们小到不值得专门做一个服务,又频繁到不能一直手动做。

一次性设置:准备标签和脚本

设置是每个字段的一次性工作。你需要标签工作室,而不是本地 Python 环境。

  1. 打开要自动化的标签,在 LPSNG 标签工作室中选择该字段。选择一个映射到文本或条码元素的字段。
  2. 附加 Python 脚本块,通过字段脚本 API 将其附加到该字段。脚本由平台与标签一起存储和管理——打印客户端上无需安装解释器。
  3. 使用脚本上下文。 该块可以看到字段的当前值,并在打印前返回修改后的值。确切的上下文变量在 Python API 参考中有定义——读一遍,然后复制该模式。
  4. 保存标签。 从此以后,每个渲染此标签的作业都会运行该脚本。

一个规范化序列号的最小块:

# Field: serial
# Runs before rendering. Input: the value passed in the print job.
raw = str(value).strip()

if raw.isdigit():
    value = f"SN-{int(raw):06d}"
else:
    value = raw.upper()

还有一个是盖上打印时间戳,而不是信任数据:

# Field: printed_at
from datetime import datetime

value = datetime.now().strftime("%Y-%m-%d %H:%M")

在托管平台而不是自己的代码中做这件事的价值在于,脚本是标签的一部分:它与标签一起版本化,跨作业复用,并且不会与模板失去同步。

复用才是真正的回报。 一旦脚本正确,就把同一个块附加到每个需要相同转换的字段上——跨标签、跨打印机。十个都以相同方式打印序列号的标签模板,就是十个以相同方式失败的模板,而修复只需在一个地方。

构建自动化流程:从数据到打印

脚本附加好之后,流程就是:认证、提交打印作业、让标签完成工作。

认证一次

LPSNG 的 Web 服务接口使用 OAuth2,采用简化的注册协议,通过单个 URL 连接外部系统。注册一次,将令牌存储在密钥库中,并使其远离你的代码仓库:

export LPSNG_BASE_URL="https://lpsng.rsj.de"   # host of your edition
export LPSNG_TOKEN="<token from the OAuth2 registration>"

提交作业

Web 服务 API 接受打印作业,将单个标签渲染为 PDF 或 PNG,并支持直接打印。确切的端点路径和负载模式来自 Web 服务接口文档——下面的代码片段展示了调用的形态,不能替代参考文档:

import os
import requests

BASE = os.environ["LPSNG_BASE_URL"]
TOKEN = os.environ["LPSNG_TOKEN"]

job = {
    # Payload keys are illustrative — use the schema from the
    # web service interface documentation.
    "label": "shipping-label",
    "printer": "warehouse-zebra-01",
    "data": {
        "order_id": "A-10442",
        "serial": "42",          # the field script turns this into SN-000042
        "printed_at": "",        # left empty on purpose
    },
}

resp = requests.post(
    f"{BASE}/<print-endpoint-from-the-docs>",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json=job,
    timeout=30,
)
resp.raise_for_status()
print(resp.json())   # the response gives you the reference to poll

注意调用方不做什么:它不格式化序列号,也不填写 printed_at。这些现在是标签的工作。

有趣的情况:计算值

最快收回成本的转换是校验位,因为校验位错误意味着扫描器在包装站拒绝该标签。脚本从作业传入的值计算它:

# Field: ean
# Compute the mod-10 check digit for a 12-digit payload.
digits = [int(c) for c in str(value) if c.isdigit()]

if len(digits) == 12:
    checksum = (10 - (sum(digits[::2]) + 3 * sum(digits[1::2])) % 10) % 10
    value = "".join(map(str, digits)) + str(checksum)
else:
    # Defensive: don't render an invalid barcode silently.
    value = "INVALID"

因为脚本在条码渲染之前修改字段值,条码内容反映计算出的结果。你不需要单独的条码生成步骤。

对比:困难的方式

替代方案是在上游计算这些值:一个预处理器读取你的订单数据,重写每个字段,然后才调用 API。它能工作,直到预处理器和标签模板产生分歧——一个补到六位,另一个补到八位——而没人注意到,直到一托盘货带着不可读的序列号发出去。将逻辑保留在模板内部意味着每个字段只有恰好一个"正确"的定义。

如果你需要在没有浏览器的环境中运行相同的标签逻辑,LPSNG Player 是一个独立的命令行打印引擎,接受一个包加数据,并生成 PDF、PNG、JSON、直接打印或 ESL 更新。相同的标签,相同的脚本,不同的执行上下文。

自动化打印中的监控和故障处理

一个静默失败的自动化流程比手动流程更糟糕,因为没人在看标签。

监控队列。 Web UI 有一个作业队列,Web 服务 API 让你检查作业状态。轮询提交后得到的引用,使用退避策略,并在作业在同一状态停留过久时告警:

import time

def wait_for_job(session, base, job_ref, timeout=120, interval=5):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        status = session.get(
            f"{base}/<job-status-endpoint-from-the-docs>/{job_ref}",
            timeout=15,
        ).json()
        if status.get("state") in ("done", "failed"):
            return status
        time.sleep(interval)
    raise TimeoutError(f"job {job_ref} did not finish in {timeout}s")

已发布的接口文档记录了作业提交、单标签渲染、直接打印和状态——它没有描述 webhook,所以轮询是应该基于的模式。如果你需要推送通知,请将其视为需要在你这边解决的缺口。

在脚本内部防御性地失败。 在事情发生之前决定坏输入应该怎么做。一个在条码字段中渲染 INVALID 的脚本,比一个抛出异常并导致整个作业失败的脚本——或者一个抛出异常、被吞掉、然后打印未格式化值的脚本——对你更有帮助。查看字段脚本 API 文档了解平台如何报告失败的块,并编写脚本使失败模式是你选择的那个。

用渲染输出做试运行。 Web 服务 API 可以将单个标签渲染为 PDF 或 PNG。打印前先渲染。这是你拥有的最便宜的冒烟测试:给脚本喂一个已知输入,查看输出,然后才将流程指向打印机。

Python 字段脚本的最佳实践

  • 每个脚本一个转换。 一个既格式化日期又查找客户名称又重新计算总数的块,是没人会在凌晨两点调试的块。
  • 保持幂等。 重新打印会发生——卡住的标签、被拒的纸箱、按了两次打印的操作员。如果 SN-000042 再次经过脚本,它应该输出 SN-000042,而不是 SN-SN-000042。在转换之前检查值是否已经具有预期的形态。
  • 在 LPSNG 外部对脚本进行版本控制。 将标签定义及其脚本块保存在 Git 中,并附上每个脚本存在原因的简短说明。平台存储并运行它们;它不能替代代码审查。
  • 永远不要硬编码数据。 没有固定的客户编号,没有固定的日期,没有打印机特定的分支逻辑。一切都应该来自字段值或打印作业中传入的数据。
  • 保持轻量。 避免长时间运行的操作。字段脚本在打印路径中运行,慢脚本就是慢标签。
  • 用真实的异常情况测试。 空字符串、前导零、已经格式化的值、过长的值。这些正是字段脚本出问题的地方。

FAQ

Python 字段脚本可以访问外部 API 或数据库吗?

字段脚本 API 设计用于在标签上下文中访问和修改字段值。对于外部数据,你通常会在打印作业数据中传入。查看 LPSNG 文档了解对外部调用的任何限制。

字段脚本中可用的 Python 版本和库是什么?

确切的 Python 环境在 LPSNG 字段脚本 API 文档中有说明。建议使用标准库功能并保持脚本轻量。

字段脚本如何与条码配合工作?

脚本可以在条码渲染之前修改字段值,允许你计算校验位、格式化数据或应用影响条码内容的转换。

脚本执行时间有限制吗?

字段脚本应该高效。虽然所提供的信息中没有详细说明具体限制,但最佳实践是避免长时间运行的操作。参考 LPSNG 文档了解任何约束。

结论

模式很简单,这就是它经得起考验的原因:将转换一次性附加到字段上,认证一次,永远提交作业。手动编辑消失了,正确标签的定义恰好存在于一个地方——模板——而不是取决于今天早上碰巧在打印机旁的那个人。

从一个字段开始。选择你的团队最常编辑的那个,写十行 Python,渲染一个 PDF,并与已知良好的标签进行比较。然后做下一个。

Next Generation Label Printing System 是运行这些脚本的托管平台——标签工作室、OAuth2 Web 服务接口、作业队列和 Player——无需维护本地 Python 环境。你可以在 lpsng.rsj.de 看到全貌。

相关文章

EU label: AI-generated content