Con il parametro di configurazione use_proto_plus, puoi specificare se vuoi che la libreria restituisca messaggi proto-plus o messaggi protobuf. Per informazioni dettagliate su come impostare questo parametro, consulta la documentazione sulla configurazione.
Questa sezione descrive le implicazioni sul rendimento di ogni opzione, in modo che tu possa scegliere l'approccio migliore per la tua applicazione.
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 standard. Tuttavia, ciò significa che l'utilizzo di proto-plus introduce un sovraccarico delle prestazioni.
Prestazioni di Proto-plus
Uno dei vantaggi principali di proto-plus è che converte i messaggi protobuf e i tipi noti in tipi Python integrati tramite un processo chiamato marshalling 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 protobuf:
syntax = "proto3";
message Dog {
string name = 1;
}
Quando questa definizione viene convertita in una classe proto-plus, ha 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 Python integrato a un tipo string in modo che sia compatibile con il runtime protobuf.
Il tempo impiegato per eseguire queste conversioni di tipo ha un impatto sulle prestazioni abbastanza grande da farti decidere, in base alle esigenze della tua applicazione, se utilizzare messaggi proto-plus o 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 è ideale per scrivere codice gestibile e leggibile. Poiché espongono oggetti Python standard, sono più facili da usare e comprendere.
- Casi d'uso dei messaggi Protobuf
- Utilizza i protobuf per i 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
BatchJobServiceoOfflineUserDataJobService.
Cambiare dinamicamente i tipi di messaggio
Dopo aver selezionato il tipo di messaggio appropriato per la tua app, potresti scoprire di dover utilizzare l'altro tipo per un flusso di lavoro specifico. In questo caso, puoi
passare dinamicamente da un tipo all'altro utilizzando le utilità offerte dalla libreria
client. Utilizzando la stessa classe di messaggi Dog di prima:
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 e le sezioni seguenti evidenziano le differenze chiave che influiscono sui casi d'uso comuni per la 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 dei campi
Il metodo helper della maschera del campo fornito da api-core è
progettato per utilizzare le istanze dei messaggi protobuf. 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 enum integrato di Python e pertanto ereditano una serie di metodi di convenienza.
Recupero del tipo di enum
Quando utilizzi il metodo GoogleAdsClient.get_type per recuperare gli enum, i messaggi restituiti sono leggermente diversi a seconda che tu utilizzi 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, esiste un attributo di convenienza nelle istanze GoogleAdsClient che ha un'interfaccia coerente indipendentemente dal tipo di messaggio che utilizzi:
val = client.enums.CampaignStatusEnum.PAUSED
Recupero dei valori enum
A volte è utile conoscere il valore o l'ID campo di una determinata enumerazione, 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 # Native protobuf enum fields already store the integer value (3): print(campaign.status) # Or look up the integer value from the enum name string: print(status_enum.CampaignStatus.Value("PAUSED"))
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
l'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 print(status_enum.CampaignStatus.Name(campaign.status))
Campi ripetuti
Come descritto nella documentazione di proto-plus, i campi ripetuti sono
generalmente equivalenti a elenchi digitati, 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 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 comuni di list, 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 messaggi ai campi ripetuti
Se il campo ripetuto non è un tipo scalare, il comportamento quando li aggiungi 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
Assegnare campi ripetuti
Per i campi ripetuti scalari e non scalari, puoi assegnare 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 uno dei suoi campi è impostato.
- Messaggi Proto-plus
# When using proto-plus messages you can check the message for truthiness. is_empty = not bool(campaign)
- Messaggi Protobuf
is_empty = campaign.ByteSize() == 0
Copia del messaggio
Per i messaggi proto-plus e protobuf, utilizza il metodo helper copy_from su
GoogleAdsClient:
client.copy_from(campaign, other_campaign)
Campi del messaggio vuoti
La procedura per impostare i campi dei messaggi vuoti è la stessa indipendentemente dal tipo di messaggio che utilizzi. Copia un messaggio vuoto nel campo in questione. Consulta la sezione Copia del messaggio e la guida Campi del messaggio vuoti. L'esempio seguente mostra come impostare un campo del messaggio vuoto:
client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))
Nomi dei campi che sono parole riservate
Quando utilizzi i messaggi proto-plus, i nomi dei campi vengono visualizzati automaticamente con un trattino basso finale se il nome è anche una parola riservata in Python. L'esempio seguente
mostra come utilizzare 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. È possibile accedervi anche a livello programmatico.
Innanzitutto, installa il modulo:
python -m pip install gapic-generator
Poi, in un REPL o script Python:
import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)
Presenza dei campi
Poiché i campi nelle istanze dei messaggi 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 un sottomessaggio, un campo oneof o un campo scalare optional
di un messaggio è stato impostato, anche se è stato impostato su un valore predefinito.
La chiamata di HasField su campi scalari non facoltativi in proto3 genera un
ValueError.
Metodi dei messaggi Protobuf
L'interfaccia del messaggio protobuf include alcuni metodi pratici che non fanno parte dell'interfaccia proto-plus. Tuttavia, puoi accedervi convertendo un messaggio proto-plus nella sua controparte protobuf:
# Accessing the ListFields method
protobuf_campaign = util.convert_proto_plus_to_protobuf(campaign)
print(protobuf_campaign.ListFields())
# Accessing the Clear method
protobuf_campaign = util.convert_proto_plus_to_protobuf(campaign)
protobuf_campaign.Clear()
Monitoraggio problemi
Se hai domande su queste modifiche o problemi durante la migrazione all'ultima versione della libreria, apri un problema in Issue Tracker.