Con il parametro di configurazione use_proto_plus
, puoi specificare se la libreria deve restituire messaggi proto-plus o messaggi protobuf. Per maggiori dettagli su come impostare questo parametro, consulta la documentazione di configurazione.
Questa sezione descrive le implicazioni sul rendimento della scelta dei tipi di messaggi da utilizzare. Ti consigliamo quindi di leggere e comprendere le opzioni per prendere una decisione consapevole.
Messaggi proto-plus e protobuf
La pipeline del generatore di codice integra proto-plus per migliorare l'ergonomia dell'interfaccia dei messaggi protobuf facendoli comportare più come oggetti Python nativi. Tuttavia, l'utilizzo di proto-plus introduce un sovraccarico delle prestazioni.
Rendimento di Proto-plus
Uno dei vantaggi principali di proto-plus è che converte i messaggi protobuf e i tipi noti in tipi Python nativi tramite un processo chiamato marshaling dei tipi.
Il marshalling si verifica quando si accede a un campo in un'istanza di messaggio proto-plus, in particolare quando un campo viene letto o impostato, ad esempio in una definizione di protobuf:
syntax = "proto3";
message Dog {
string name = 1;
}
Quando questa definizione viene convertita in una classe proto-plus, avrà il seguente aspetto:
import proto
class Dog(proto.Message):
name = proto.Field(proto.STRING, number=1)
Puoi quindi inizializzare la classe Dog
e accedere al relativo campo name
come faresti con qualsiasi altro oggetto Python:
dog = Dog()
dog.name = "Scruffy"
print(dog.name)
Quando viene letto e impostato il campo name
, il valore viene convertito da un tipo str
di Python nativo a un tipo string
in modo che sia compatibile con il runtime di protobuf.
In base alle nostre analisi sul rendimento, abbiamo stabilito che il tempo impiegato per eseguire questo tipo di conversioni ha un impatto sul rendimento sufficientemente elevato da richiedere agli utenti di decidere, in base alle proprie esigenze, se utilizzare o meno i messaggi protobuf.
Casi d'uso per i messaggi proto-plus e protobuf
- Casi d'uso dei messaggi Proto-plus
- Proto-plus offre una serie di miglioramenti ergonomici rispetto ai messaggi protobuf, quindi sono ideali per scrivere codice leggibile e manutenibile. Poiché espongono oggetti Python nativi, sono più facili da usare e comprendere.
- Casi d'uso dei messaggi Protobuf
- Utilizza i protobuf per casi d'uso sensibili al rendimento, in particolare nelle app che devono elaborare rapidamente report di grandi dimensioni o che creano richieste di modifica con un numero elevato di operazioni, ad esempio con
BatchJobService
oOfflineUserDataJobService
.
Tipi di messaggi che cambiano dinamicamente
Dopo aver selezionato il tipo di messaggio appropriato per la tua app, potresti scoprire
che devi utilizzare l'altro tipo per un flusso di lavoro specifico. In questo caso, è facile passare dinamicamente da un tipo all'altro utilizzando le utilità offerte dalla libreria client. Utilizzando la stessa classe di messaggio Dog
di cui sopra:
from google.ads.googleads import util
# Proto-plus message type
dog = Dog()
# Protobuf message type
dog = util.convert_proto_plus_to_protobuf(dog)
# Back to proto-plus message type
dog = util.convert_protobuf_to_proto_plus(dog)
Differenze nell'interfaccia dei messaggi Protobuf
L'interfaccia proto-plus è documentata in dettaglio, ma qui evidenzieremo alcune differenze chiave che influiscono sui casi d'uso comuni della libreria client Google Ads.
Serializzazione dei byte
- Messaggi proto-plus
serialized = type(campaign).serialize(campaign) deserialized = type(campaign).deserialize(serialized)
- Messaggi Protobuf
serialized = campaign.SerializeToString() deserialized = campaign.FromString(serialized)
Serializzazione JSON
- Messaggi proto-plus
serialized = type(campaign).to_json(campaign) deserialized = type(campaign).from_json(serialized)
- Messaggi protobuf
from google.protobuf.json_format import MessageToJson, Parse serialized = MessageToJson(campaign) deserialized = Parse(serialized, campaign)
Maschere di campo
Il metodo di assistenza per la maschera del campo fornito da api-core è progettato per utilizzare le istanze di messaggio protobuf. Pertanto, quando utilizzi i messaggi proto-plus, convertili in messaggi protobuf per utilizzare l'helper:
- Messaggi proto-plus
from google.api_core.protobuf_helpers import field_mask campaign = client.get_type("Campaign") protobuf_campaign = util.convert_proto_plus_to_protobuf(campaign) mask = field_mask(None, protobuf_campaign)
- Messaggi Protobuf
from google.api_core.protobuf_helpers import field_mask campaign = client.get_type("Campaign") mask = field_mask(None, campaign)
Enum
Gli enum esposti dai messaggi proto-plus sono istanze del tipo nativo di Python
enum
e quindi ereditano una serie di metodi di utilità.
Recupero del tipo di enum
Quando utilizzi il metodo GoogleAdsClient.get_type
per recuperare gli enum, i messaggi
che vengono restituiti sono leggermente diversi a seconda che tu stia utilizzando
messaggi proto-plus o protobuf. Ad esempio:
- Messaggi proto-plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
- Messaggi protobuf
val = client.get_type("CampaignStatusEnum").PAUSED
Per semplificare il recupero degli enum, è disponibile un attributo di praticità sulle istanze GoogleAdsClient
che ha un'interfaccia coerente indipendentemente dal tipo di messaggio utilizzato:
val = client.enums.CampaignStatusEnum.PAUSED
Recupero del valore enum
A volte è utile conoscere il valore o l'ID campo di un determinato enum, ad esempio PAUSED
in CampaignStatusEnum
corrisponde a 3
:
- Messaggi proto-plus
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the value of campaign status print(campaign.status.value)
- Messaggi Protobuf
campaign = client.get_type("Campaign") status_enum = client.enums.CampaignStatusEnum campaign.status = status_enum.PAUSED # To read the value of campaign status print(status_enum.CampaignStatus.Value(campaign.status))
Recupero del nome dell'enum
A volte è utile conoscere il nome di un campo enum. Ad esempio, quando
leggi gli oggetti dall'API, potresti voler sapere a quale stato della campagna corrisponde il valore intero 3
:
- Messaggi proto-plus
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the name of campaign status print(campaign.status.name)
- Messaggi protobuf
campaign = client.get_type("Campaign") status_enum = client.enums.CampaignStatusEnum # Sets the campaign status to the int value for PAUSED campaign.status = status_enum.PAUSED # To read the name of campaign status status_enum.CampaignStatus.Name(campaign.status)
Campi ripetuti
Come descritto nella documentazione di proto-plus,
i campi ripetuti sono in genere equivalenti a elenchi di tipo, il che significa che
si comportano quasi in modo identico a un list
.
Aggiungere valori ai campi scalari ripetuti
Quando aggiungi valori a campi ripetuti di tipo scalare, ad esempio i campi string
o int64
, l'interfaccia è la stessa indipendentemente dal tipo di messaggio:
- Messaggi proto-plus
ad.final_urls.append("https://www.example.com")
- Messaggi Protobuf
ad.final_urls.append("https://www.example.com")
Sono inclusi anche tutti gli altri metodi list
comuni, ad esempio extend
:
- Messaggi proto-plus
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
- Messaggi protobuf
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
Aggiungere tipi di messaggio ai campi ripetuti
Se il campo ripetuto non è di tipo scalare, il comportamento durante l'aggiunta ai campi ripetuti è leggermente diverso:
- Messaggi proto-plus
frequency_cap = client.get_type("FrequencyCapEntry") frequency_cap.cap = 100 campaign.frequency_caps.append(frequency_cap)
- Messaggi protobuf
# The add method initializes a message and adds it to the repeated field frequency_cap = campaign.frequency_caps.add() frequency_cap.cap = 100
Assegna campi ripetuti
Per i campi ripetuti scalari e non scalari, puoi assegnare gli elenchi al campo in diversi modi:
- Messaggi proto-plus
# In proto-plus it's possible to use assignment. urls = ["https://www.example.com"] ad.final_urls = urls
- Messaggi protobuf
# Protobuf messages do not allow assignment, but you can replace the # existing list using slice syntax. urls = ["https://www.example.com"] ad.final_urls[:] = urls
Messaggi vuoti
A volte è utile sapere se un'istanza di messaggio contiene informazioni o se ha i suoi campi impostati.
- Messaggi proto-plus
# When using proto-plus messages you can simply check the message for # truthiness. is_empty = bool(campaign) is_empty = not campaign
- Messaggi protobuf
is_empty = campaign.ByteSize() == 0
Testo del messaggio
Per i messaggi proto-plus e protobuf, ti consigliamo di utilizzare il metodo di assistenza copy_from
su GoogleAdsClient
:
client.copy_from(campaign, other_campaign)
Campi messaggio vuoti
La procedura per impostare campi di messaggio vuoti è la stessa indipendentemente dal tipo di messaggio utilizzato. Devi solo copiare un messaggio vuoto nel campo in questione. Consulta la sezione Testo del messaggio e la guida Campi messaggio vuoti. Ecco un esempio di come impostare un campo del messaggio vuoto:
client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))
Nomi di campi che sono parole riservate
Quando utilizzi i messaggi proto-plus, i nomi dei campi vengono visualizzati automaticamente con un underscore finale se il nome è anche una parola riservata in Python. Ecco un
esempio di utilizzo di un'istanza Asset
:
asset = client.get_type("Asset")
asset.type_ = client.enums.AssetTypeEnum.IMAGE
L'elenco completo dei nomi riservati viene creato nel modulo gapic generator. Inoltre, è possibile accedervi anche in modo programmatico.
Innanzitutto, installa il modulo:
python -m pip install gapic-generator
Quindi, in uno script o in una REPL Python:
import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)
Presenza sul campo
Poiché i campi delle istanze di messaggio protobuf hanno valori predefiniti, non è sempre intuitivo sapere se un campo è stato impostato o meno.
- Messaggi proto-plus
# Use the "in" operator. has_field = "name" in campaign
- Messaggi protobuf
campaign = client.get_type("Campaign") # Determines whether "name" is set and not just an empty string. campaign.HasField("name")
L'interfaccia della classe protobuf
Message
ha un metodo HasField
che determina se il campo di un messaggio è stato impostato, anche se è stato impostato su un valore predefinito.
Metodi dei messaggi protobuf
L'interfaccia dei messaggi protobuf include alcuni metodi di utilità che non fanno parte dell'interfaccia proto-plus. Tuttavia, è facile accedervi convertendo un messaggio proto-plus nella relativa controparte protobuf:
# Accessing the ListFields method
protobuf_campaign = util.convert_protobuf_to_proto_plus(campaign)
print(campaign.ListFields())
# Accessing the Clear method
protobuf_campaign = util.convert_protobuf_to_proto_plus(campaign)
print(campaign.Clear())
Monitoraggio problemi
Per eventuali domande su queste modifiche o problemi di migrazione alla versione più recente della libreria, registra un problema nel nostro tracker.