1 04/05/2026 9 min

Se devi creare un codice a barre con Python, la scelta giusta non è “una libreria qualsiasi”, ma il formato che ti serve davvero. Code 128, EAN-13, UPC, ITF e QR non rispondono agli stessi vincoli: alcuni richiedono checksum, altri hanno lunghezze fisse, altri ancora sono pensati per etichette logistiche o per cataloghi retail. In pratica, il lavoro serio non è generare l’immagine: è produrre un simbolo leggibile, con dimensioni corrette, margini adeguati e dati coerenti con lo standard.

Nel mondo Python la via più comoda per i codici a barre lineari è spesso python-barcode. Se invece devi gestire QR o altri codici bidimensionali, conviene usare librerie dedicate, perché i requisiti di rendering e correzione errore sono diversi. Qui restiamo sui codici a barre classici, quelli che trovi su etichette prodotto, scaffali, spedizioni e documenti interni.

Formato giusto prima della libreria

Prima di scrivere una riga di codice, chiarisci questi punti:

  1. Tipo di codice: EAN-13 per prodotti retail, Code 128 per dati alfanumerici più flessibili, Code 39 per casi semplici e compatibilità ampia.
  2. Dati da codificare: numerici puri, alfanumerici, prefissi interni, seriali, SKU.
  3. Output richiesto: PNG, SVG, PDF o stampa diretta.
  4. Vincoli di scansione: dimensione minima, quiet zone, contrasto, qualità della stampante.

Il punto critico è questo: un codice “bello” a schermo può essere inutilizzabile in produzione. Il lettore ottico non perdona margini stretti, scaling sbagliato o immagini compresse male. Se il codice finisce su etichette termiche, la differenza la fanno i millimetri, non l’estetica.

Installazione rapida della libreria Python

Per iniziare con i codici a barre lineari, installa python-barcode e, se vuoi esportare in PNG, anche Pillow. Per SVG basta la libreria base.

python3 -m pip install python-barcode pillow

Se lavori in un ambiente virtuale, meglio ancora: eviti conflitti con versioni di sistema e repliche il setup in modo pulito.

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install python-barcode pillow

Per verificare che il pacchetto sia disponibile, puoi controllare il modulo importabile e la versione installata.

python -c "import barcode; print(barcode.__file__)"

Se il comando fallisce, il problema non è il barcode ma l’ambiente Python: interprete errato, venv non attivo o installazione andata su un’altra versione.

Creare un EAN-13 valido

EAN-13 è il caso più delicato perché non accetta dati arbitrari. Devi fornire 12 cifre e lasciare che la libreria calcoli il checksum, oppure fornire direttamente 13 cifre già corrette. Se sbagli la lunghezza, il risultato non è “approssimato”: è semplicemente non conforme.

Ecco un esempio minimale che genera un file SVG e un PNG partendo da un codice EAN-13.

from barcode import EAN13
from barcode.writer import ImageWriter

numero = "590123412345"
barcode = EAN13(numero, writer=ImageWriter())
barcode.save("ean13_prodotto")

Il file prodotto sarà qualcosa come ean13_prodotto.png. Se invece vuoi SVG, puoi omettere ImageWriter() e salvare il simbolo vettoriale. Il vantaggio dell’SVG è evidente quando devi stampare o ridimensionare senza perdere definizione.

Per sapere se il dato è davvero accettato, prova con un input volutamente errato e osserva l’eccezione: è il modo più veloce per capire se stai rispettando il formato richiesto. In un flusso reale, il controllo deve stare prima della generazione, non dopo.

from barcode import EAN13

try:
    EAN13("12345")
except Exception as e:
    print(type(e).__name__, e)

Code 128 per dati alfanumerici

Se devi codificare stringhe interne, SKU o identificativi alfanumerici, Code 128 è spesso la scelta più pratica. È più denso di Code 39 e gestisce un set di caratteri molto più utile in automazione e magazzino. Per molti casi operativi è il formato di default: compatto, leggibile e abbastanza flessibile.

Generarlo è semplice:

from barcode import Code128
from barcode.writer import ImageWriter

codice = "INV-2026-000184"
bar = Code128(codice, writer=ImageWriter())
bar.save("codice_inventario")

Qui non hai il vincolo della lunghezza fissa, ma resta il problema della leggibilità. Se il contenuto è lungo, il simbolo si allarga. Questo non è un bug: è fisica. Più dati inserisci, più spazio serve per mantenere larghezza minima degli elementi e margine esterno sufficiente.

Se il tuo obiettivo è stampare etichette piccole, valuta se il dato può essere abbreviato o se conviene separare il codice leggibile dal testo umano. Un barcode troppo compresso è peggio di un codice più lungo ma scansionabile al primo colpo.

Controllare rendering, dimensioni e quiet zone

Il rendering non va lasciato ai valori di default se l’output finisce su stampa o in un gestionale. I parametri del writer cambiano direttamente la qualità finale: modulo, altezza, margini, testo sotto il simbolo. Qui si gioca buona parte della riuscita pratica.

Un esempio con opzioni esplicite:

from barcode import Code128
from barcode.writer import ImageWriter

options = {
    "module_width": 0.2,
    "module_height": 15.0,
    "quiet_zone": 6.5,
    "font_size": 10,
    "text_distance": 2.0,
    "write_text": True,
}

bar = Code128("ABC-12345", writer=ImageWriter())
bar.save("barcode_eticchetta", options=options)

La quiet zone è il margine bianco ai lati del codice. Se la riduci troppo, molti scanner iniziano a fallire o diventano sensibili all’inquadratura. In ambiente industriale o retail, è uno degli errori più frequenti: il codice “si vede”, ma non si legge in modo affidabile.

Se vuoi misurare rapidamente l’effetto dei parametri, genera più versioni con valori diversi e confronta il tasso di lettura su uno scanner reale o su un’app affidabile di test. La metrica utile non è la dimensione del file: è il tempo medio di acquisizione e la percentuale di letture corrette.

Salvare in PNG o SVG: quando scegliere uno o l’altro

PNG va bene se il flusso è già rasterizzato e sai esattamente a quale risoluzione stamperai. SVG è preferibile quando l’etichetta deve essere scalata, impaginata o passata a un sistema di stampa che accetta vettoriale. In generale, se non hai un vincolo specifico, SVG è la scelta più robusta.

Con SVG eviti l’effetto seghettato e la perdita di dettaglio causata dal ridimensionamento. Con PNG, invece, devi stare più attento alla risoluzione finale: se esporti troppo piccolo e poi ingrandisci, il barcode perde precisione geometrica.

Un flusso pratico per esportare un SVG e poi convertirlo, se necessario, è questo:

from barcode import Code128

bar = Code128("ABC-12345")
bar.save("barcode_vettoriale")

Se il tuo ambiente richiede conversione successiva, puoi usare strumenti esterni come Inkscape o pipeline di stampa che interpretano direttamente l’SVG. Il vantaggio è mantenere il simbolo pulito fino all’ultimo passaggio.

Validare il codice generato prima di usarlo in produzione

La validazione non dovrebbe limitarsi a “il file esiste”. Devi verificare almeno tre cose: coerenza del dato, leggibilità del file prodotto e conformità del formato. Se il barcode è destinato a processi operativi, aggiungi una lettura di controllo con scanner o software di decoding.

  1. Controllo input: lunghezza, charset, checksum se richiesto.
  2. Controllo output: file generato, dimensioni, margini, contrasto.
  3. Controllo funzionale: scansione reale da dispositivo o software.

Un controllo utile lato Python è anche la gestione delle eccezioni. Se il dato è invalido, il tuo script deve fermarsi e segnalare chiaramente il problema invece di produrre un’immagine inutilizzabile.

from barcode import Code128
from barcode.errors import BarcodeError

try:
    bar = Code128("dato non valido")
    bar.save("test")
except BarcodeError as e:
    print("Barcode non generato:", e)

In un sistema più strutturato, il passo successivo è integrare questa verifica in una pipeline: generazione, controllo file, eventuale conversione, stampa. È un flusso piccolo, ma se lo automatizzi bene riduci parecchi errori manuali.

Integrare la generazione in uno script operativo

Quando il barcode serve in produzione, lo script non deve essere un prototipo monolitico. Conviene separare input, validazione, generazione e output. Così puoi riusare la stessa logica per etichette diverse, batch notturni o integrazioni con ERP e gestionali.

Un esempio di struttura minima:

import sys
from barcode import Code128
from barcode.writer import SVGWriter


def genera_barcode(valore: str, nome_file: str) -> None:
    codice = Code128(valore, writer=SVGWriter())
    codice.save(nome_file)


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Uso: python barcode.py VALORE NOME_FILE")
        sys.exit(1)
    genera_barcode(sys.argv[1], sys.argv[2])

Questo approccio è più pulito perché ti permette di aggiungere controlli senza toccare la parte di rendering. Per esempio, puoi imporre un prefisso obbligatorio, normalizzare spazi e trattini, oppure bloccare input troppo lunghi prima ancora di arrivare al writer.

Se lavori in ambienti multiutente o su server condivisi, non dimenticare i permessi sui file di output e la directory di destinazione. Un barcode generato correttamente ma salvato nel posto sbagliato è un problema operativo, non tecnico, ma il risultato è lo stesso: fermo processo o etichetta mancante.

Errori tipici che fanno perdere tempo

Gli errori più comuni sono quasi sempre gli stessi:

  • Input non conforme al formato scelto, soprattutto per EAN e UPC.
  • Margini troppo piccoli, quindi scansione intermittente.
  • Test fatto solo su schermo e non su carta o etichetta reale.
  • Immagine compressa o ridimensionata dal sistema di stampa.
  • Uso del formato sbagliato per il caso d’uso, ad esempio Code 39 dove servirebbe Code 128.

Se il tuo barcode non si legge, la prima domanda non è “la libreria funziona?”, ma “lo standard è corretto e il simbolo è stato stampato con geometria stabile?”. Nella pratica, il 90% dei problemi sta lì.

Quando non basta Python puro

Python è ottimo per la generazione, ma non sempre basta per l’intero ciclo. Se devi impaginare etichette complesse, produrre PDF con layout multipli o stampare su driver specifici, spesso conviene affiancare strumenti come reportlab, librerie PDF o il motore di stampa già usato in azienda.

La regola pratica è semplice: usa Python per produrre il dato corretto e il simbolo corretto; usa lo strumento più adatto per impaginazione, stampa e distribuzione. Mischiare tutto in uno script unico rende il debug più lento e aumenta il rischio di introdurre errori di rendering difficili da vedere a occhio.

Verifica finale su un caso reale

Se vuoi chiudere il lavoro in modo professionale, fai sempre una prova completa su supporto reale. Genera il barcode, stampalo nelle condizioni previste, leggilo con il dispositivo che verrà usato in produzione e annota il risultato. Se serve, correggi solo uno parametro alla volta: altezza, quiet zone, font, dimensione finale.

In altre parole, il codice a barre con Python non è un esercizio di sintassi. È una piccola catena di affidabilità: input pulito, formato giusto, rendering controllato, stampa coerente, scansione verificata. Se uno di questi anelli salta, il problema emerge sempre nel punto più scomodo, cioè quando l’etichetta è già uscita dalla stampante.