Mit dem Konfigurationsparameter use_proto_plus können Sie angeben, ob die Bibliothek Proto-Plus-Nachrichten oder Protobuf-Nachrichten zurückgeben soll. Weitere Informationen zum Festlegen dieses Parameters finden Sie in der Konfigurationsdokumentation.
In diesem Abschnitt werden die Auswirkungen der einzelnen Optionen auf die Leistung beschrieben, damit Sie den besten Ansatz für Ihre Anwendung auswählen können.
Proto-plus- und Protobuf-Nachrichten
Die Codegenerator-Pipeline integriert proto-plus, um die Ergonomie der protobuf-Nachrichtenschnittstelle zu verbessern, indem sie sich eher wie Standard-Python-Objekte verhält. Dies bedeutet jedoch, dass die Verwendung von proto-plus zu einem Leistungsaufwand führt.
Proto-Plus-Leistung
Einer der Hauptvorteile von proto-plus ist, dass protobuf-Nachrichten und bekannte Typen durch einen Prozess namens Typ-Marshalling in integrierte Python-Typen konvertiert werden.
Das Marshalling erfolgt, wenn auf ein Feld in einer Proto-Plus-Nachrichteninstanz zugegriffen wird, insbesondere wenn ein Feld entweder gelesen oder festgelegt wird, z. B. in einer Protobuf-Definition:
syntax = "proto3";
message Dog {
string name = 1;
}
Wenn diese Definition in eine Proto-Plus-Klasse konvertiert wird, sieht sie so aus:
import proto
class Dog(proto.Message):
name = proto.Field(proto.STRING, number=1)
Anschließend können Sie die Klasse Dog initialisieren und wie bei jedem anderen Python-Objekt auf das Feld name zugreifen:
dog = Dog()
dog.name = "Scruffy"
print(dog.name)
Beim Lesen und Festlegen des Felds name wird der Wert von einem integrierten Python-Typ str in einen string-Typ konvertiert, damit der Wert mit der Protobuf-Laufzeit kompatibel ist.
Die Zeit, die für diese Typkonvertierungen aufgewendet wird, hat einen so großen Einfluss auf die Leistung, dass Sie je nach den Anforderungen Ihrer Anwendung entscheiden sollten, ob Sie Proto-Plus- oder Protobuf-Nachrichten verwenden möchten.
Anwendungsfälle für Proto-Plus- und Protobuf-Nachrichten
- Anwendungsfälle für Proto-Plus-Nachrichten
- Proto-plus bietet eine Reihe von ergonomischen Verbesserungen gegenüber protobuf-Nachrichten und eignet sich daher ideal zum Schreiben von wartbarem, lesbarem Code. Da sie Standard-Python-Objekte verfügbar machen, sind sie einfacher zu verwenden und zu verstehen.
- Anwendungsfälle für Protobuf-Nachrichten
- Verwenden Sie Protobufs für leistungssensitive Anwendungsfälle, insbesondere in Apps, die große Berichte schnell verarbeiten müssen oder Mutationsanfragen mit einer großen Anzahl von Vorgängen erstellen, z. B. mit
BatchJobServiceoderOfflineUserDataJobService.
Nachrichtentypen dynamisch wechseln
Nachdem Sie den geeigneten Nachrichtentyp für Ihre App ausgewählt haben, kann es sein, dass Sie für einen bestimmten Workflow den anderen Typ verwenden müssen. In diesem Fall können Sie mithilfe der von der Clientbibliothek angebotenen Dienstprogramme dynamisch zwischen den beiden Typen wechseln. Verwenden Sie dieselbe Dog-Nachrichtenklasse wie zuvor:
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)
Unterschiede bei der Protobuf-Nachrichtenschnittstelle
Die Proto-Plus-Schnittstelle ist ausführlich dokumentiert. In den folgenden Abschnitten werden die wichtigsten Unterschiede beschrieben, die sich auf gängige Anwendungsfälle für die Google Ads-Clientbibliothek auswirken.
Byte-Serialisierung
- Proto-plus-Nachrichten
serialized = type(campaign).serialize(campaign) deserialized = type(campaign).deserialize(serialized)
- Protobuf-Nachrichten
serialized = campaign.SerializeToString() deserialized = campaign.FromString(serialized)
JSON-Serialisierung
- Proto-plus-Nachrichten
serialized = type(campaign).to_json(campaign) deserialized = type(campaign).from_json(serialized)
- Protobuf-Nachrichten
from google.protobuf.json_format import MessageToJson, Parse serialized = MessageToJson(campaign) deserialized = Parse(serialized, campaign)
Feldmasken
Die von api-core bereitgestellte Hilfsmethode für Feldmasken ist für die Verwendung von Protobuf-Nachrichteninstanzen konzipiert. Wenn Sie proto-plus-Nachrichten verwenden, konvertieren Sie sie in protobuf-Nachrichten, um den Helper zu verwenden:
- Proto-plus-Nachrichten
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)
- Protobuf-Nachrichten
from google.api_core.protobuf_helpers import field_mask campaign = client.get_type("Campaign") mask = field_mask(None, campaign)
Enums
Enums, die von proto-plus-Nachrichten bereitgestellt werden, sind Instanzen des integrierten Python-Typs enum und übernehmen daher eine Reihe von Komfortmethoden.
Enum-Typ abrufen
Wenn Sie die Methode GoogleAdsClient.get_type zum Abrufen von Enums verwenden, unterscheiden sich die zurückgegebenen Nachrichten geringfügig, je nachdem, ob Sie Proto-Plus- oder Protobuf-Nachrichten verwenden. Beispiel:
- Proto-plus-Nachrichten
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
- Protobuf-Nachrichten
val = client.get_type("CampaignStatusEnum").PAUSED
Um das Abrufen von Enums zu vereinfachen, gibt es ein praktisches Attribut für GoogleAdsClient-Instanzen, das unabhängig vom verwendeten Nachrichtentyp eine einheitliche Schnittstelle hat:
val = client.enums.CampaignStatusEnum.PAUSED
Abruf von Enum-Werten
Manchmal ist es nützlich, den Wert oder die Feld-ID eines bestimmten Enums zu kennen. Beispielsweise entspricht PAUSED in CampaignStatusEnum dem Wert 3:
- Proto-plus-Nachrichten
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the value of campaign status print(campaign.status.value)
- Protobuf-Nachrichten
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"))
Enum-Namen abrufen
Manchmal ist es nützlich, den Namen eines Enum-Felds zu kennen. Wenn Sie beispielsweise Objekte aus der API lesen, möchten Sie vielleicht wissen, welchem Kampagnenstatus die Ganzzahl 3 entspricht:
- Proto-plus-Nachrichten
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the name of campaign status print(campaign.status.name)
- Protobuf-Nachrichten
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))
Wiederkehrende Felder
Wie in der proto-plus-Dokumentation beschrieben, entsprechen wiederkehrende Felder im Allgemeinen typisierten Listen. Das bedeutet, dass sie sich fast identisch mit einem list verhalten.
Werte an wiederkehrende Skalarfelder anhängen
Wenn Sie wiederkehrenden Feldern mit skalarem Typ, z. B. string- oder int64-Feldern, Werte hinzufügen, ist die Schnittstelle unabhängig vom Nachrichtentyp gleich:
- Proto-plus-Nachrichten
ad.final_urls.append("https://www.example.com")
- Protobuf-Nachrichten
ad.final_urls.append("https://www.example.com")
Dies gilt auch für alle anderen gängigen list-Methoden, z. B. extend:
- Proto-plus-Nachrichten
ad.final_urls.extend( ["https://www.example.com", "https://www.example.com/2"] )
- Protobuf-Nachrichten
ad.final_urls.extend( ["https://www.example.com", "https://www.example.com/2"] )
Nachrichtentypen an wiederkehrende Felder anhängen
Wenn das wiederkehrende Feld kein skalarer Typ ist, unterscheidet sich das Verhalten beim Hinzufügen zu wiederkehrenden Feldern geringfügig:
- Proto-plus-Nachrichten
frequency_cap = client.get_type("FrequencyCapEntry") frequency_cap.cap = 100 campaign.frequency_caps.append(frequency_cap)
- Protobuf-Nachrichten
# The add method initializes a message and adds it to the repeated field frequency_cap = campaign.frequency_caps.add() frequency_cap.cap = 100
Wiederkehrende Felder zuweisen
Sowohl für skalare als auch für nicht skalare wiederkehrende Felder können Sie dem Feld auf verschiedene Weise Listen zuweisen:
- Proto-plus-Nachrichten
# In proto-plus it's possible to use assignment. urls = ["https://www.example.com"] ad.final_urls = urls
- Protobuf-Nachrichten
# 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
Leere Nachrichten
Manchmal ist es nützlich zu wissen, ob eine Nachrichteninstanz Informationen enthält oder ob eines ihrer Felder festgelegt ist.
- Proto-plus-Nachrichten
# When using proto-plus messages you can check the message for truthiness. is_empty = not bool(campaign)
- Protobuf-Nachrichten
is_empty = campaign.ByteSize() == 0
Nachrichtentext
Verwenden Sie sowohl für Proto-Plus- als auch für Protobuf-Nachrichten die Hilfsmethode copy_from für GoogleAdsClient:
client.copy_from(campaign, other_campaign)
Leere Nachrichtenfelder
Das Verfahren zum Festlegen leerer Nachrichtenfelder ist unabhängig vom verwendeten Nachrichtentyp immer gleich. Sie kopieren eine leere Nachricht in das entsprechende Feld. Weitere Informationen finden Sie im Abschnitt Nachrichtenkopie und im Leitfaden Leere Nachrichtenfelder. Das folgende Beispiel zeigt, wie Sie ein leeres Nachrichtenfeld festlegen:
client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))
Feldnamen, die reservierte Wörter sind
Bei Verwendung von Proto-Plus-Nachrichten werden Feldnamen automatisch mit einem nachgestellten Unterstrich angezeigt, wenn der Name auch ein reserviertes Wort in Python ist. Das folgende Beispiel zeigt, wie Sie mit einer Asset-Instanz arbeiten:
asset = client.get_type("Asset")
asset.type_ = client.enums.AssetTypeEnum.IMAGE
Die vollständige Liste der reservierten Namen wird im Modul gapic generator erstellt. Der Zugriff ist auch programmatisch möglich.
Installieren Sie zuerst das Modul:
python -m pip install gapic-generator
Dann in einer Python-REPL oder einem Python-Script:
import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)
Feldpräsenz
Da die Felder in Protobuf-Nachrichteninstanzen Standardwerte haben, ist es nicht immer intuitiv, ob ein Feld festgelegt wurde oder nicht.
- Proto-plus-Nachrichten
# Use the "in" operator. has_field = "name" in campaign
- Protobuf-Nachrichten
campaign = client.get_type("Campaign") # Determines whether "name" is set and not just an empty string. campaign.HasField("name")
Die Protobuf-Klassenschnittstelle Message hat eine HasField-Methode, die bestimmt, ob eine Unternachricht, ein oneof-Feld oder ein skalares optional-Feld in einer Nachricht festgelegt wurde, auch wenn es auf einen Standardwert festgelegt wurde.
(Wenn Sie HasField für nicht optionale Skalarfelder in proto3 aufrufen, wird ein ValueError ausgelöst.)
Protobuf-Nachrichtenmethoden
Die Protobuf-Nachrichtenschnittstelle enthält einige praktische Methoden, die nicht Teil der Proto-Plus-Schnittstelle sind. Sie können jedoch darauf zugreifen, indem Sie eine Proto-Plus-Nachricht in ihr Protobuf-Äquivalent konvertieren:
# 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()
Issue Tracker
Wenn Sie Fragen zu diesen Änderungen oder Probleme bei der Migration zur aktuellen Version der Bibliothek haben, melden Sie das Problem im Issue Tracker.