Esempio completo funzionante disponibile su GitHub:
manage-xmp-in-psd-and-ai-files-python

Introduzione

Un team di marketing carica 400 file PSD nella tua piattaforma di asset. Il caricamento funziona. La ricerca no, perché nessuno dei file contiene parole chiave, metà manca di un avviso di copyright e i nomi dei designer vivono solo in un foglio di calcolo da qualche parte. La soluzione non è un foglio di calcolo più grande. La gestione di XMP è una funzionalità di GroupDocs.Metadata per Python tramite .NET che legge e scrive il pacchetto di metadati incorporato nei file Photoshop PSD e Illustrator AI, il che significa che i dati di proprietà e di ricerca possono vivere nei file stessi.

XMP è un pacchetto XML all’interno di un contenitore binario, organizzato in schemi: Dublin Core per i campi che ogni sistema comprende, lo schema Photoshop per il contesto editoriale, XmpBasic per l’identità dello strumento. Analizzare manualmente un PSD per raggiungere quel pacchetto è davvero difficile. Con la classe Metadata sono tre ricerche di attributi, e lo stesso codice serve anche per i file AI.

Questo tutorial mostra il ciclo completo in quattro passaggi: catturare l’intero pacchetto, leggere gli schemi che contano, scrivere copyright e creatore, e taggare parole chiave per la ricerca. Ogni frammento proviene da un repository eseguibile che verifica che i valori scritti persistano.

Prerequisiti

Prima di iniziare, assicurati di avere:

  • Python 3 con pip
  • GroupDocs.Metadata per Python tramite .NET (il repository fissa la versione 26.5)
  • Un file PSD o AI su cui sperimentare

Installazione

pip install groupdocs-metadata-net==26.5

Passo 1 - Cattura l’intero pacchetto XMP

Inizia osservando tutto ciò che il file contiene. La cattura percorre il pacchetto radice, ogni schema registrato e infine scandisce l’albero delle proprietà per qualsiasi cosa non standard, raccogliendola tutta in un unico dizionario piatto.

result = {}

def put(props, prop):
    value = (str(prop.interpreted_value) if prop.interpreted_value is not None
             else (str(prop.value) if prop.value is not None else ""))
    props[prop.name] = value

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is not None:
        for p in xmp:                                  # proprietà del pacchetto radice
            put(result, p)
        schemes = xmp.schemes
        for scheme in (schemes.dublin_core, schemes.xmp_basic, schemes.photoshop,
                       schemes.camera_raw, schemes.paged_text,
                       schemes.xmp_dynamic_media, schemes.xmp_media_management):
            if scheme is None:
                continue
            for p in scheme:
                put(result, p)
    for p in metadata.find_properties(lambda p: p.name is not None):
        if p.name not in result:                       # cattura pacchetti personalizzati
            put(result, p)

Punti chiave:

  • interpreted_value prima: date ed enumerazioni arrivano in forma leggibile dall’uomo invece che grezze.
  • Sette schemi più una scansione: il passaggio finale find_properties cattura i pacchetti dei fornitori che gli schemi nominati non rilevano.
  • Un solo file aperto: l’intera cattura costa un unico contesto Metadata, il che è importante per l’ingestione di massa.

Suggerimento: indicizza questo dizionario al momento dell’ingestione e la maggior parte delle domande successive sui metadati diventerà una ricerca nel dizionario invece di letture di file.

Quale schema XMP dovrebbe leggere per prima la mia integrazione?

Inizia con Dublin Core. I suoi nove campi dc: contengono titolo, creatore, diritti e soggetto, valori su cui la maggior parte dei sistemi DAM, degli indici di ricerca e dei controlli di licenza concordano, e sia i file PSD sia AI li espongono in modo identico. Leggi lo schema Photoshop al secondo posto per il contesto editoriale, ad esempio City, Credit e DateCreated. Riserva la scansione completa del pacchetto per i lavori di ingestione che devono catturare tutto.

Passo 2 - Leggi gli schemi che rispondono a domande reali

Per il codice in fase di richiesta, limita la lettura a un solo schema. Dublin Core risponde a domande di proprietà e di ricerca:

dc_fields = {}
with Metadata("campaign-hero.psd") as metadata:
    xmp = getattr(metadata.get_root_package(), "xmp_package", None)
    dc = xmp.schemes.dublin_core if xmp is not None else None
    if dc is not None:
        for p in dc:
            dc_fields[p.name] = (str(p.interpreted_value)
                                 if p.interpreted_value is not None else
                                 str(p.value) if p.value is not None else "")

print(dc_fields.get("dc:rights", "<no rights recorded>"))

Lo schema Photoshop funziona allo stesso modo tramite proprietà tipizzate: ps.color_mode, ps.icc_profile, ps.city, ps.country, ps.date_created, ps.caption_writer, ps.credit e ps.source, ognuna letta con una guardia None. Questi sono i campi su cui Bridge, Lightroom e i filtri di ricerca DAM si basano per i file Adobe.

Nota cosa succede con file senza XMP: le guardie producono un dizionario vuoto, non un’eccezione. Gli asset esportati di recente rendono questo caso comune, quindi mantieni questo comportamento nella tua integrazione.

Le stesse tre ricerche funzionano sui file Illustrator. Sostituisci campaign-hero.psd con brand-mark.ai e nulla cambia, il che rende realistico un unico percorso di codice per archivi Adobe misti. In pratica, un’esportazione AI fresca tende a contenere meno schemi popolati rispetto a un salvataggio Photoshop, quindi il percorso del dizionario vuoto viene esercitato più spesso lì.

Ora il percorso di scrittura. Il timbro di proprietà tocca tre campi affinché ogni lettore veda la stessa identità: dc:rights per l’avviso legale, dc:creator come lista ordinata, e xmp:CreatorTool per gli strumenti che leggono lo schema XmpBasic invece di Dublin Core. Una volta ho perso un pomeriggio a causa di un banner di licenza che mostrava “Unknown author” su asset che i designer giuravano fossero etichettati; i valori erano in dc:creator mentre lo strumento leggeva solo xmp:CreatorTool. Scrivere entrambi ha risolto quel tipo di bug.

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is None:                          # il file non ha affatto XMP
        root.xmp_package = XmpPacketWrapper()
        xmp = root.xmp_package
    if xmp.schemes.dublin_core is None:
        xmp.schemes.dublin_core = XmpDublinCorePackage()

    dc = xmp.schemes.dublin_core
    dc.set_rights("(C) 2026 GroupDocs Sample")
    dc.set("dc:creator", XmpArray.from_(["Digital Asset Team"],
                                        XmpArrayType.ORDERED))

    if xmp.schemes.xmp_basic is None:
        xmp.schemes.xmp_basic = XmpBasicPackage()
    xmp.schemes.xmp_basic.creator_tool = "Digital Asset Team"

    metadata.save("campaign-hero-stamped.psd")

Punti chiave:

  • Le guardie creano livelli mancanti: XmpPacketWrapper e XmpDublinCorePackage vengono creati su richiesta, così la scrittura funziona anche su file privi di XMP.
  • Array ORDINATO per i creatori: l’ordine dell’autore ha significato, quindi la lista dei creatori usa un XmpArray ordinato.
  • Salva in un nuovo percorso: il file sorgente rimane intatto, che è l’impostazione corretta per le fasi di esportazione.

Passo 4 - Tagga le parole chiave per la ricerca

dc:subject è il sacchetto di parole chiave per gli indici di ricerca DAM. La scrittura sostituisce l’intero sacchetto in una chiamata:

with Metadata("campaign-hero.psd") as metadata:
    root = metadata.get_root_package()
    xmp = getattr(root, "xmp_package", None)
    if xmp is None:
        root.xmp_package = XmpPacketWrapper()
        xmp = root.xmp_package
    if xmp.schemes.dublin_core is None:
        xmp.schemes.dublin_core = XmpDublinCorePackage()

    xmp.schemes.dublin_core.set(
        "dc:subject",
        XmpArray.from_(["landscape", "sunset", "commercial"],
                       XmpArrayType.UNORDERED))
    metadata.save("campaign-hero-tagged.psd")

Le parole chiave usano un array UNORDERED perché l’ordine non ha importanza per un indicizzatore. E poiché set sostituisce il sacchetto esistente, leggi prima le parole chiave attuali e uniscile in Python quando hai bisogno di aggiungere tag anziché sostituirli.

Per verificare qualsiasi scrittura, riesegui il lettore del Passo 2 sul file di output. Il repository automatizza esattamente questo: rilegge i propri output e verifica che la stringa di copyright e la prima parola chiave sopravvivano nei byte salvati.

Applicazioni nel mondo reale

Ingestione DAM

Esegui la cattura del Passo 1 su ogni file in ingresso e memorizza il dizionario accanto al record dell’asset. Ricerca, deduplicazione e controlli di diritti quindi operano sul tuo database invece di riaprire i file binari. La cattura del piccolo PSD di esempio del repository restituisce già una buona serie di proprietà in un solo passaggio, e la stessa chiamata mantiene la sua forma quando l’input diventa una cartella di migliaia di file.

Applicazione delle licenze

Prima che un asset venga inviato a un portale cliente, richiedi un dc:rights non vuoto. I file che non lo hanno ricevono automaticamente il trattamento del Passo 3, così nulla parte senza un avviso.

Rietichettatura batch

Quando la tassonomia cambia, leggi dc:subject di ogni file, mappa i termini vecchi a quelli nuovi in Python e scrivi il sacchetto unito con il Passo 4. Sia gli archivi PSD sia AI usano lo stesso ciclo. Nessuna licenza Photoshop è necessaria.

Migliori pratiche e suggerimenti

  • Considera vuoto come normale: i file senza XMP sono routine, non errori; il pattern di ritorno anticipato mantiene i flussi di lavoro fluidi.
  • Unisci prima di scrivere parole chiave: set sostituisce dc:subject, quindi il tagging additivo richiede lettura, estensione, scrittura.
  • Scrivi l’identità in entrambi gli schemi: accoppiare dc:creator con xmp:CreatorTool mantiene allineati i lettori Dublin Core e XmpBasic.
  • Verifica le scritture con una lettura di ritorno: una rilettura dopo il salvataggio è poco costosa e cattura subito eventuali sorprese del contenitore.
  • Licenza per la produzione: la modalità di valutazione esegue tutto ciò che è mostrato qui; usa una licenza prima di timbrare asset reali dei clienti.

Conclusione

Leggere e scrivere XMP nei file Adobe si riduce a tre operazioni: risolvere il pacchetto tramite get_root_package(), proteggere lo schema necessario e leggere o scrivere valori tipizzati. Con queste mosse hai costruito un ciclo completo in questo tutorial, dalla cattura del pacchetto alle letture degli schemi, al timbro di copyright e al tagging delle parole chiave, con lo stesso codice per file PSD e AI.

Pronto a implementarlo nel tuo progetto? Ecco i prossimi passi:

Risorse aggiuntive

Domande sul tuo flusso di lavoro XMP? Chiedi sul support forum.