Protokollzwischenspeicher-Nachrichten

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 Leistungsauswirkungen der Auswahl der Nachrichtentypen beschrieben. Wir empfehlen Ihnen daher, die Optionen zu lesen und zu verstehen, um eine fundierte Entscheidung treffen zu können.

Proto-plus- und Protobuf-Nachrichten im Vergleich

Die Codegenerator-Pipeline integriert proto-plus, um die Ergonomie der Protobuf-Nachrichtenschnittstelle zu verbessern, indem sie sich eher wie native Python-Objekte verhalten. Die Verwendung von Proto-Plus führt jedoch zu einem Leistungsaufwand.

Leistung von proto-plus

Einer der Hauptvorteile von proto-plus besteht darin, dass Protobuf-Nachrichten und bekannte Typen durch einen Prozess namens Typ-Marshalling in native Python-Typen umgewandelt werden.

Das Marshaling erfolgt, wenn in einer proto-plus-Nachrichteninstanz auf ein Feld zugegriffen wird, insbesondere wenn ein Feld 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 in etwa so aus:

import proto

class Dog(proto.Message):
    name = proto.Field(proto.STRING, number=1)

Sie können dann die Dog-Klasse initialisieren und wie bei jedem anderen Python-Objekt auf das name-Feld zugreifen:

dog = Dog()
dog.name = "Scruffy"
print(dog.name)

Beim Lesen und Festlegen des Felds name wird der Wert von einem nativen Python-str-Typ in einen string-Typ konvertiert, damit der Wert mit der protobuf-Laufzeit kompatibel ist.

Unsere Leistungsanalysen haben gezeigt, dass die Zeit, die für diese Art von Conversions aufgewendet wird, einen erheblichen Leistungsimpact hat. Daher sollten Nutzer je nach Bedarf entscheiden, ob sie 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, lesbaren Code. Da sie native Python-Objekte zur Verfügung stellen, sind sie einfacher zu verwenden und zu verstehen.
Anwendungsfälle für Protobuf-Nachrichten
Verwenden Sie Protokollpuffer für leistungsorientierte Anwendungsfälle, insbesondere in Anwendungen, in denen große Berichte schnell verarbeitet werden müssen oder in denen mutate-Anfragen mit einer großen Anzahl von Vorgängen erstellt werden, z. B. mit BatchJobService oder OfflineUserDataJobService.

Dynamisch wechselnde Nachrichtentypen

Nachdem Sie den passenden Nachrichtentyp für Ihre Anwendung ausgewählt haben, müssen Sie möglicherweise für einen bestimmten Workflow den anderen Nachrichtentyp verwenden. In diesem Fall ist es mithilfe der Dienstprogramme der Clientbibliothek ganz einfach, dynamisch zwischen den beiden Typen zu wechseln. Mit derselben Dog-Nachrichtenklasse wie oben:

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 in der Protobuf-Nachrichtenoberfläche

Die Proto-Plus-Benutzeroberfläche ist detailliert dokumentiert. Im Folgenden gehen wir auf einige wichtige Unterschiede ein, 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. Konvertieren Sie Proto-Plus-Nachrichten daher in Protobuf-Nachrichten, um den Helfer 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

Von Proto-Plus-Nachrichten freigegebene Enums sind Instanzen des nativen Python-Typs enum und erben daher eine Reihe von Methoden zur Vereinfachung.

Abruf des Enum-Typs

Wenn Sie die Methode GoogleAdsClient.get_type zum Abrufen von Enumerationen 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
Protokollzwischenspeicher-Nachrichten
val = client.get_type("CampaignStatusEnum").PAUSED

Zur Vereinfachung des Abrufens von Enums gibt es ein Convenience-Attribut für GoogleAdsClient-Instanzen, die unabhängig vom verwendeten Nachrichtentyp eine konsistente Schnittstelle haben:

val = client.enums.CampaignStatusEnum.PAUSED

Abrufen von Enum-Werten

Manchmal ist es hilfreich, den Wert oder die Feld-ID eines bestimmten Enums zu kennen. Beispielsweise entspricht PAUSED im CampaignStatusEnum der 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
# To read the value of campaign status
print(status_enum.CampaignStatus.Value(campaign.status))

Enum-Namen abrufen

Manchmal ist es hilfreich, den Namen eines Enum-Felds zu kennen. Wenn Sie beispielsweise Objekte aus der API lesen, möchten Sie möglicherweise 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
status_enum.CampaignStatus.Name(campaign.status)

Wiederkehrende Felder

Wie in den Proto-Plus-Dokumenten beschrieben, sind wiederholte Felder im Allgemeinen mit typisierten Listen gleichzusetzen. Das bedeutet, dass sie sich fast identisch wie eine list verhalten.

Werte an wiederkehrende skalare Felder anhängen

Wenn Sie Feldern vom Skalartyp, z. B. string- oder int64-Feldern, Werte hinzufügen, ist die Benutzeroberfläche 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")

Dazu gehören auch 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 wiederholte Feld keinen skalären Typ hat, ist das Verhalten beim Hinzufügen zu wiederholten Feldern etwas anders:

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 skalaren als auch nicht skalaren wiederkehrenden Feldern können Sie Listen auf unterschiedliche Weise 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 hilfreich 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 simply check the message for
# truthiness.
is_empty = bool(campaign)
is_empty = not campaign
Protobuf-Nachrichten
is_empty = campaign.ByteSize() == 0

Nachrichtentext

Für proto-plus- und protobuf-Nachrichten empfehlen wir die Verwendung der Helper-Methode copy_from für die GoogleAdsClient:

client.copy_from(campaign, other_campaign)

Leere Nachrichtenfelder

Das Festlegen leerer Nachrichtenfelder ist unabhängig vom verwendeten Nachrichtentyp identisch. Sie müssen dazu nur eine leere Nachricht in das entsprechende Feld kopieren. Weitere Informationen finden Sie im Abschnitt Nachrichtentext sowie im Leitfaden Leere Nachrichtenfelder. Hier ein Beispiel für ein leeres Nachrichtenfeld:

client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))

Feldnamen, die reservierte Wörter sind

Bei der Verwendung von Proto-Plus-Nachrichten werden Feldnamen automatisch mit einem nachfolgenden Unterstrich angezeigt, wenn der Name auch ein reserviertes Wort in Python ist. Hier ein Beispiel für die Arbeit mit einer Asset-Instanz:

asset = client.get_type("Asset")
asset.type_ = client.enums.AssetTypeEnum.IMAGE

Die vollständige Liste der reservierten Namen wird im Modul gapic generator erstellt. Es kann auch programmatisch abgerufen werden.

Installieren Sie zuerst das Modul:

python -m pip install gapic-generator

Führen Sie dann in einer Python-REPL oder einem Python-Skript folgende Schritte aus:

import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)

Präsenz vor Ort

Da die Felder in protobuf-Nachrichteninstanzen Standardwerte haben, ist es nicht immer intuitiv zu erkennen, 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, mit der ermittelt wird, ob das Feld in einer Nachricht festgelegt wurde, auch wenn es auf einen Standardwert festgelegt wurde.

Protobuf-Nachrichtenmethoden

Die protobuf-Nachrichtenschnittstelle enthält einige praktische Methoden, die nicht Teil der proto-plus-Schnittstelle sind. Sie können jedoch einfach darauf zugreifen, indem Sie eine proto-plus-Nachricht in ihr protobuf-Gegenstück konvertieren:

# 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())

Problemverfolgung

Wenn Sie Fragen zu diesen Änderungen oder Problemen bei der Migration zur neuesten Version der Bibliothek haben, erstellen Sie bitte ein Problem in unserem Tracker.