Protokollzwischenspeicher-Nachrichten

Mit der Version 14.0.0 der Python-Clientbibliothek wird der neue erforderliche Konfigurationsparameter use_proto_plus eingeführt. Dieser gibt an, 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 wird beschrieben, wie sich die Auswahl der zu verwendenden Nachrichtentypen auf die Leistung auswirkt. Wir empfehlen Ihnen daher, die Optionen zu lesen und zu verstehen, um eine fundierte Entscheidung zu treffen. Wenn Sie jedoch ein Upgrade auf Version 14.0.0 ausführen möchten, ohne Änderungen am Code vorzunehmen, können Sie use_proto_plus auf True setzen, um funktionsgefährdende Änderungen an der Benutzeroberfläche zu vermeiden.

Proto-Plus- und protobuf-Nachrichten im Vergleich

In Version 10.0.0 wurde die Python-Clientbibliothek zu einer neuen Codegenerator-Pipeline migriert, die proto-plus integriert hat, um die Ergonomie der protobuf-Nachrichtenschnittstelle durch ihr Verhalten wie native Python-Objekte zu verbessern. Der Nachteil bei dieser Verbesserung besteht darin, dass Proto-Plus zu Leistungseinbußen führt.

Proto-Plus-Leistung

Einer der Hauptvorteile von proto-plus besteht darin, dass protobuf-Nachrichten und bekannte Typen mithilfe eines Prozesses namens Type-Marshaling in native Python-Typen konvertiert werden.

Das Marshaling findet statt, 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)

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 nativen Python-str-Typ in einen string-Typ konvertiert, damit der Wert mit der protobuf-Laufzeit kompatibel ist.

In der Analyse, die wir seit der Veröffentlichung von Version 10.0.0 durchgeführt haben, haben wir festgestellt, dass sich die Zeit, die für diese Typkonvertierungen aufgewendet wird, stark auf die Leistung auswirkt. Daher ist es wichtig, Nutzern die Möglichkeit zu geben, protobuf-Nachrichten zu verwenden.

Anwendungsfälle für proto-plus- und protobuf-Nachrichten

Anwendungsfälle für Proto Plus-Nachrichten
Proto-Plus bietet im Vergleich zu protobuf-Nachrichten eine Reihe von ergonomischen Verbesserungen, sodass sie ideal zum Schreiben von verwaltbarem, lesbarem Code sind. 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.

Nachrichtentypen dynamisch ändern

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 einfach, mithilfe der Dienstprogramme der Clientbibliothek dynamisch zwischen den beiden Typen zu wechseln. Mit derselben Nachrichtenklasse Dog 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-Oberfläche ist ausführlich dokumentiert. An dieser Stelle möchten wir jedoch einige wichtige Unterschiede hervorheben, die sich auf häufige Anwendungsfälle für die Google Ads-Clientbibliothek auswirken.

Byte-Serialisierung

Proto Plus-Nachrichten
serialized = type(campaign).serialize(campaign)
deserialized = type(campaign).deserialize(serialized)
Protokollzwischenspeicher-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)
Protokollzwischenspeicher-Nachrichten
from google.protobuf.json_format import MessageToJson, Parse

serialized = MessageToJson(campaign)
deserialized = Parse(serialized, campaign)

Feldmasken

Die von api-core bereitgestellte Feldmaskenhilfemethode ist für die Verwendung von protobuf-Nachrichteninstanzen ausgelegt. Wenn Sie also proto-plus-Nachrichten verwenden, konvertieren Sie sie in protobuf-Nachrichten, um das Hilfsprogramm 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)
Protokollzwischenspeicher-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 nativen Python-Typs enum und übernehmen daher eine Reihe praktischer Methoden.

Abruf des Enum-Typs

Wenn Sie Enums mit der Methode GoogleAdsClient.get_type abrufen, unterscheiden sich die zurückgegebenen Nachrichten geringfügig davon, 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

Abruf 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)
Protokollzwischenspeicher-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))

Abrufen von Enum-Namen

Manchmal ist es hilfreich, 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)
Protokollzwischenspeicher-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 wiederkehrende Felder im Allgemeinen typisierten Listen gleichwertig. Das heißt, sie verhalten sich fast identisch mit einem list.

An wiederkehrende skalare Felder anfügen

Wenn Sie wiederkehrenden skalaren Feldern Werte hinzufügen, z. B. den Feldern string oder int64, ist die Schnittstelle unabhängig vom Nachrichtentyp gleich:

Proto Plus-Nachrichten
ad.final_urls.append("https://www.example.com")
Protokollzwischenspeicher-Nachrichten
ad.final_urls.append("https://www.example.com")

Dies schließt auch alle anderen gängigen list-Methoden ein, z. B. extend:

Proto Plus-Nachrichten
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
Protokollzwischenspeicher-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)
Protokollzwischenspeicher-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 Arten Listen zuweisen:

Proto Plus-Nachrichten
# In proto-plus it's possible to use assignment.
urls = ["https://www.example.com"]
ad.final_urls = urls
Protokollzwischenspeicher-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
Protokollzwischenspeicher-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

Der Vorgang zum Festlegen leerer Nachrichtenfelder ist unabhängig vom verwendeten Nachrichtentyp gleich. Sie müssen nur eine leere Nachricht in das entsprechende Feld kopieren. Weitere Informationen finden Sie im Abschnitt Nachrichtentext und im Leitfaden Leere Nachrichtenfelder. Hier ist ein Beispiel, wie ein leeres Nachrichtenfeld festgelegt wird:

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 nachgestellten 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 gapic-Generator-Modul erstellt. Der Zugriff ist auch programmatisch möglich.

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)

Feldpräsenz

Da die Felder in protobuf-Nachrichteninstanzen Standardwerte haben, ist es nicht immer intuitiv zu wissen, ob ein Feld festgelegt wurde oder nicht.

Proto Plus-Nachrichten
# Use the "in" operator.
has_field = "name" in campaign
Protokollzwischenspeicher-Nachrichten
campaign = client.get_type("Campaign")
# Determines whether "name" is set and not just an empty string.
campaign.HasField("name")

Die Schnittstelle der protobuf-Klasse Message hat eine HasField-Methode, die bestimmt, ob das Feld für eine Nachricht festgelegt wurde, auch wenn es auf einen Standardwert gesetzt war.

Protokollzwischenspeicher-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 du Fragen zu diesen Änderungen oder Probleme bei der Migration zu Version 14.0.0 der Bibliothek hast, kannst du das Problem über unseren Tracker melden.