Automatización de la impresión de etiquetas con scripts de campo de Python
La etiqueta casi siempre está bien. La fecha está desactualizada, el número de serie perdió sus ceros iniciales y el total necesita un dígito de control antes de que el código de barras se pueda escanear. Así que alguien abre la plantilla de la etiqueta en el diseñador, edita tres campos, pulsa imprimir y mañana por la mañana hace exactamente lo mismo.
Esa edición no pertenece a una plantilla. Pertenece al código que se ejecuta en el momento de la impresión. RSJ LPSNG te permite adjuntar un bloque de script de Python directamente a un campo de la etiqueta, de modo que la transformación ocurre dentro de la plantilla: sin paso de preprocesamiento, sin el ritual de “primero arregla el CSV” entre tu ERP y la impresora.
Este artículo trata sobre la automatización a nivel de campo: qué es un script de campo, cómo configurarlo una vez, cómo controlarlo desde la API del servicio web y cómo evitar que rompa silenciosamente tu línea de producción.
Dos temas adyacentes se tratan en otro lugar: el contenido que cambia por pedido está en Building Order-Specific Labeling on Top of a Label Printing API, y las etiquetas basadas en datos de hojas de cálculo están en How to Create Labels from Excel Data Files and Lookup Tables. Aquí nos mantenemos en el campo.
¿Por qué automatizar la impresión de etiquetas con scripts de campo de Python?
Los scripts de campo se ejecutan dentro de la plantilla de la etiqueta. El bloque de Python se adjunta a un campo y obtiene acceso al valor actual de ese campo, que puede modificar antes de que se renderice la etiqueta. Esa única decisión de diseño cambia el flujo de trabajo:
- Sin preprocesamiento externo. No necesitas un script que reescriba tus datos de entrada antes de enviarlos. Los datos entran tal como están; la etiqueta corrige lo que haga falta.
- Consistencia entre clientes. El script viaja con la etiqueta. Ya sea que el trabajo provenga de la interfaz web, de la API del servicio web o del LPSNG Player, el mismo campo recibe el mismo tratamiento.
- La lógica es revisable. Vive junto al campo que afecta, no en un cron job en el portátil de alguien.
Las tareas que justifican esto son aburridas y repetitivas:
| Tarea | Enfoque manual | Script de campo |
|---|---|---|
| Marca de tiempo de impresión | Escribir la fecha de hoy en el campo | Formatear el valor en el momento del renderizado |
| Números de serie | Rellenar a mano, olvidar uno, reimprimir | Normalizar a un ancho fijo |
| Dígitos de control | Calcular en una hoja de cálculo | Calcular a partir del valor del campo |
| Etiquetas derivadas | Copiar un valor de otro campo | Hacer referencia al campo de origen |
Ninguna de estas es difícil. Ese es el punto: son demasiado pequeñas para merecer un servicio y demasiado frecuentes para seguir haciéndolas a mano.
Configuración única: preparar tu etiqueta y el script
La configuración es un trabajo único por campo. Necesitas el estudio de etiquetas, no un entorno local de Python.
- Abre la etiqueta que quieres automatizar en el estudio de etiquetas de LPSNG y selecciona el campo. Elige un campo que se mapee a un elemento de texto o de código de barras.
- Adjunta un bloque de script de Python a ese campo mediante la API de scripts de campo. El script es almacenado y gestionado por la plataforma junto con la etiqueta: no hay intérprete que instalar en el cliente de impresión.
- Usa el contexto del script. El bloque ve el valor actual del campo y devuelve uno modificado antes de imprimir. Las variables de contexto exactas se definen en la referencia de la API de Python: léela una vez y luego copia el patrón.
- Guarda la etiqueta. A partir de aquí, cada trabajo que renderice esta etiqueta ejecuta el script.
Un bloque mínimo que normaliza un número de serie:
# 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()
Y uno que estampa la hora de impresión en lugar de confiar en los datos:
# Field: printed_at
from datetime import datetime
value = datetime.now().strftime("%Y-%m-%d %H:%M")
El valor de hacer esto en una plataforma gestionada en lugar de en tu propio código es que el script forma parte de la etiqueta: se versiona con ella, se reutiliza entre trabajos y no puede desincronizarse de la plantilla.
La reutilización es la verdadera recompensa. Una vez que un script es correcto, adjunta el mismo bloque a cada campo que necesite la misma transformación, en todas las etiquetas y en todas las impresoras. Diez plantillas de etiquetas que imprimen los números de serie de la misma manera son diez plantillas que fallan de la misma manera, y un único lugar donde arreglarlo.
Construir el flujo automatizado: de los datos a la impresión
Con el script adjunto, el flujo es: autenticar, enviar un trabajo de impresión, dejar que la etiqueta haga el trabajo.
Autenticar una vez
La interfaz de servicio web de LPSNG usa OAuth2 con un protocolo de registro simplificado que conecta un sistema externo mediante una única URL. Haz el registro una vez, guarda el token en tu almacén de secretos y mantenlo fuera de tu repositorio:
export LPSNG_BASE_URL="https://lpsng.rsj.de" # host of your edition
export LPSNG_TOKEN="<token from the OAuth2 registration>"
Enviar un trabajo
La API del servicio web acepta trabajos de impresión, renderiza etiquetas individuales como PDF o PNG y admite impresión directa. Las rutas exactas de los endpoints y el esquema de la carga útil provienen de la documentación de la interfaz de servicio web: el fragmento siguiente muestra la forma de la llamada, no un sustituto de la referencia:
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
Fíjate en lo que el llamador no hace: no formatea el número de serie y no rellena printed_at. Eso ahora es trabajo de la etiqueta.
El caso interesante: calcular un valor
La transformación que se amortiza más rápido es un dígito de control, porque uno incorrecto significa que un escáner rechaza la etiqueta en la estación de empaque. El script lo calcula a partir del valor que el trabajo pasó:
# 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"
Como el script modifica el valor del campo antes de que se renderice el código de barras, el contenido del código de barras refleja el resultado calculado. No necesitas un paso separado de generación de códigos de barras.
La forma difícil, como contraste
La alternativa es calcular estos valores aguas arriba: un preprocesador que lee tus datos de pedidos, reescribe cada campo y solo entonces llama a la API. Funciona, hasta que el preprocesador y la plantilla de la etiqueta no coinciden —uno rellena a seis dígitos, el otro a ocho— y nadie se da cuenta hasta que se envía un palé con números de serie ilegibles. Mantener la lógica dentro de la plantilla significa que hay exactamente una definición de “correcto” por campo.
Si necesitas ejecutar la misma lógica de etiqueta en algún lugar sin un navegador, el LPSNG Player es un motor de impresión de línea de comandos independiente que toma un paquete más datos y produce PDF, PNG, JSON, una impresión directa o una actualización de ESL. La misma etiqueta, los mismos scripts, un contexto de ejecución diferente.
Monitoreo y manejo de fallos en la impresión automatizada
Un flujo automatizado que falla en silencio es peor que uno manual, porque nadie está mirando la etiqueta.
Vigila la cola. La interfaz web tiene una cola de trabajos, y la API del servicio web te permite consultar el estado de un trabajo. Sondea la referencia que recibiste al enviar, con retroceso exponencial, y alerta cuando un trabajo permanezca demasiado tiempo en el mismo estado:
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")
La interfaz publicada documenta el envío de trabajos, el renderizado de etiquetas individuales, la impresión directa y el estado; no describe webhooks, así que el sondeo es el patrón sobre el que construir. Si necesitas notificaciones push, trátalo como una carencia que resolver de tu lado.
Falla de forma defensiva dentro del script. Decide qué debe hacer una entrada incorrecta antes de que ocurra. Un script que renderiza INVALID en un campo de código de barras te está haciendo un favor comparado con uno que lanza una excepción y tumba todo el trabajo, o con uno que lanza una excepción, esta se traga y se imprime el valor sin formatear. Consulta la documentación de la API de scripts de campo para saber cómo informa la plataforma de un bloque fallido, y escribe tus scripts de modo que el modo de fallo sea el que tú elegiste.
Prueba en seco con la salida renderizada. La API del servicio web puede renderizar una etiqueta individual como PDF o PNG. Renderiza antes de imprimir. Es la prueba de humo más barata que tienes: dale al script una entrada conocida, mira la salida y solo entonces apunta el flujo a la impresora.
Buenas prácticas para los scripts de campo de Python
- Una transformación por script. Un bloque que formatea una fecha y busca el nombre de un cliente y recalcula un total es un bloque que nadie va a depurar a las 2 de la madrugada.
- Sé idempotente. Las reimpresiones ocurren: una etiqueta atascada, una caja rechazada, un operador que pulsa imprimir dos veces. Si
SN-000042pasa de nuevo por el script, debería salir comoSN-000042, no comoSN-SN-000042. Comprueba si el valor ya tiene la forma esperada antes de transformarlo. - Controla las versiones de los scripts fuera de LPSNG. Mantén las definiciones de las etiquetas y sus bloques de script en Git con una breve nota de por qué existe cada uno. La plataforma los almacena y los ejecuta; no sustituye la revisión de código.
- Nunca codifiques datos de forma fija. Sin números de cliente fijos, sin fechas fijas, sin lógica de ramificación específica de la impresora. Todo debería venir del valor del campo o de los datos pasados en el trabajo de impresión.
- Mantenlo ligero. Evita operaciones de larga duración. Los scripts de campo se ejecutan en la ruta de impresión, y un script lento es una etiqueta lenta.
- Prueba con rarezas reales. Cadenas vacías, ceros iniciales, valores que ya están formateados, valores demasiado largos. Ahí es donde se rompen los scripts de campo.
Preguntas frecuentes
¿Pueden los scripts de campo de Python acceder a API externas o bases de datos?
La API de scripts de campo está diseñada para acceder y modificar los valores de los campos dentro del contexto de la etiqueta. Para datos externos, normalmente los pasarías en los datos del trabajo de impresión. Consulta la documentación de LPSNG para conocer las limitaciones sobre llamadas externas.
¿Qué versión de Python y qué bibliotecas están disponibles en los scripts de campo?
El entorno exacto de Python se especifica en la documentación de la API de scripts de campo de LPSNG. Se recomienda usar las funciones de la biblioteca estándar y mantener los scripts ligeros.
¿Cómo funcionan los scripts de campo con los códigos de barras?
Los scripts pueden modificar el valor del campo antes de que se renderice el código de barras, lo que te permite calcular dígitos de control, formatear datos o aplicar transformaciones que afectan al contenido del código de barras.
¿Hay un límite en el tiempo de ejecución de los scripts?
Los scripts de campo deben ser eficientes. Aunque la información proporcionada no detalla límites específicos, es una buena práctica evitar operaciones de larga duración. Consulta la documentación de LPSNG para conocer las restricciones.
Conclusión
El patrón es simple, y por eso se mantiene: adjunta la transformación al campo una vez, autentica una vez, envía trabajos para siempre. La edición manual desaparece, y la definición de una etiqueta correcta vive en exactamente un lugar —la plantilla— en lugar de en quienquiera que estuviera en la impresora esta mañana.
Empieza con un campo. Elige el que tu equipo edita con más frecuencia, escribe diez líneas de Python, renderiza un PDF y compáralo con una etiqueta que sepas que está bien. Luego haz el siguiente.
Next Generation Label Printing System es la plataforma gestionada que ejecuta estos scripts —el estudio de etiquetas, la interfaz de servicio web OAuth2, la cola de trabajos y el Player— sin un entorno local de Python que mantener. Puedes ver el panorama completo en lpsng.rsj.de.
Entradas relacionadas
- Zebra Label Software Alternative: A Browser-Based Approach
- Building Order-Specific Labeling on Top of a Label Printing API
- How to Create Labels from Excel Data Files and Lookup Tables
