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 wird beschrieben, welche Auswirkungen die Auswahl der Nachrichtentypen auf die Leistung hat. Wir empfehlen Ihnen daher, die Optionen zu lesen und zu verstehen, um eine fundierte Entscheidung treffen zu können.
Proto-plus-Nachrichten im Vergleich zu Protokollpuffer-Nachrichten
Die Code-Generator-Pipeline integriert proto-plus, um die Ergonomie der Protobuf-Nachrichtenschnittstelle zu verbessern, indem sie sich eher wie native Python-Objekte verhält. Die Verwendung von proto-plus führt jedoch zu Leistungseinbußen.
Proto-plus-Leistung
Einer der Hauptvorteile von proto-plus ist, dass Protobuf-Nachrichten und bekannte Typen durch einen Prozess namens Typ-Marshaling in native Python-Typen konvertiert werden.
Das Marshaling erfolgt, wenn auf ein Feld in einer Proto-Plus-Nachrichteninstanz 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 Dog
-Klasse 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 vom nativen Python-Typ str
in den Typ string
konvertiert, damit er mit der Protobuf-Laufzeit kompatibel ist.
Unsere Leistungsanalysen haben ergeben, dass die für diese Typkonvertierungen benötigte Zeit einen so großen Einfluss auf die Leistung hat, dass Nutzer je nach Bedarf entscheiden sollten, 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 ergonomischer Verbesserungen gegenüber Protobuf-Nachrichten und eignet sich daher ideal zum Schreiben von wartungsfreundlichem, lesbarem Code. Da sie native Python-Objekte verfügbar machen, sind sie einfacher zu verwenden und zu verstehen.
- Anwendungsfälle für Protobuf-Nachrichten
- Verwenden Sie Protobufs für leistungsintensive Anwendungsfälle, insbesondere in Apps, in denen große Berichte schnell verarbeitet werden müssen oder in denen Änderungsanfragen mit einer großen Anzahl von Vorgängen erstellt werden, z. B. mit
BatchJobService
oderOfflineUserDataJobService
.
Nachrichtentypen dynamisch ändern
Nachdem Sie den passenden Nachrichtentyp für Ihre App ausgewählt haben, stellen Sie möglicherweise fest, dass Sie für einen bestimmten Workflow den anderen Typ verwenden müssen. In diesem Fall ist es einfach, dynamisch zwischen den beiden Typen zu wechseln, indem Sie die von der Clientbibliothek angebotenen Dienstprogramme verwenden. 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 bei der Protobuf-Nachrichtenschnittstelle
Die proto-plus-Schnittstelle ist detailliert dokumentiert. Hier werden jedoch einige wichtige Unterschiede hervorgehoben, die sich auf häufige Anwendungsfälle für die Google Ads-Clientbibliothek auswirken.
Serialisierung von Byte
- 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 also proto-plus-Nachrichten verwenden, müssen Sie sie in Protobuf-Nachrichten konvertieren, um den Helfer nutzen zu können:
- 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 nativen enum
-Typs von Python und erben daher eine Reihe von praktischen Methoden.
Abrufen des Enum-Typs
Wenn Sie die Methode GoogleAdsClient.get_type
zum Abrufen von Enums verwenden, unterscheiden sich die zurückgegebenen Meldungen 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 für GoogleAdsClient
-Instanzen ein Attribut, das unabhängig vom verwendeten Nachrichtentyp eine konsistente Schnittstelle hat:
val = client.enums.CampaignStatusEnum.PAUSED
Abrufen von Enum-Werten
Manchmal ist es nützlich, den Wert oder die Feld-ID eines bestimmten Enums zu kennen, z. B. PAUSED
für CampaignStatusEnum
entspricht 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))
Abrufen von Enum-Namen
Manchmal ist es nützlich, 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 der proto-plus-Dokumentation beschrieben, entsprechen wiederholte Felder im Allgemeinen typisierten Listen. Das bedeutet, dass sie sich fast identisch wie eine list
verhalten.
Werte an wiederholte skalare Felder anhängen
Wenn Sie Werte zu wiederholten Feldern vom Skalartyp hinzufügen, z. B. zu string
- oder int64
-Feldern, 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 wiederholte Felder anhängen
Wenn das wiederholte Feld kein Skalartyp ist, 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 für skalare als auch für nicht skalare wiederholte 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
- 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 Felder festgelegt sind.
- 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
Nachrichtenkopie
Sowohl für proto-plus- als auch für Protobuf-Nachrichten empfehlen wir die Verwendung der Hilfsmethode copy_from
für GoogleAdsClient
:
client.copy_from(campaign, other_campaign)
Leere Nachrichtenfelder
Der Vorgang zum Festlegen leerer Nachrichtenfelder ist unabhängig vom verwendeten Nachrichtentyp. Sie müssen nur eine leere Nachricht in das entsprechende Feld kopieren. Weitere Informationen finden Sie im Abschnitt Nachrichtentext sowie im Leitfaden Leere Nachrichtenfelder. Hier ein Beispiel dafür, wie Sie ein leeres Nachrichtenfeld festlegen:
client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))
Feldnamen, die reservierte Wörter sind
Wenn Sie proto-plus-Nachrichten verwenden, werden Feldnamen automatisch mit einem Unterstrich am Ende angezeigt, wenn der Name auch ein reserviertes Wort in Python ist. Hier ist 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. Sie kann auch programmatisch aufgerufen werden.
Installieren Sie zuerst das Modul:
python -m pip install gapic-generator
Führen Sie dann in einer Python-REPL oder einem Skript Folgendes 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 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-Pendant 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 haben oder Probleme bei der Migration zur neuesten Version der Bibliothek auftreten, erstellen Sie einen Fehlerbericht in unserem Tracker.