Mit der Version 14.0.0
der Python-Clientbibliothek wird ein neuer erforderlicher Konfigurationsparameter mit dem Namen 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, welche Auswirkungen die Auswahl der zu verwendenden Nachrichten auf die Leistung hat. 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 Codeänderungen vorzunehmen, können Sie use_proto_plus
auf True
setzen, um Funktionsänderungen 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 zu verbessern, indem sie sich mehr wie native Python-Objekte verhalten. Der Nachteil dieser Verbesserung besteht darin, dass proto-plus den Leistungsaufwand mit sich bringt.
Proto-Plus-Leistung
Einer der Hauptvorteile von proto-plus besteht darin, dass protobuf-Nachrichten und bekannte Typen durch einen Prozess namens Typ-Marshaling in native Python-Typen konvertiert werden.
Marshaling tritt auf, wenn von einer proto-Plus-Nachrichteninstanz auf ein Feld zugegriffen wird, insbesondere wenn ein Feld entweder gelesen oder festgelegt wird, beispielsweise 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 jedes andere Python-Objekt auf das Feld name
zugreifen:
dog = Dog()
dog.name = "Scruffy"
print(dog.name)
Beim Lesen und Festlegen des Feldes name
wird der Wert von einem nativen Python-Typ str
in einen string
-Typ konvertiert, sodass 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 die Zeit, die für diese Typkonvertierungen aufgewendet wird, sich auf die Leistung auswirkt, sodass es wichtig ist, 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 und eignet sich daher ideal zum Schreiben von verwaltbarem, lesbarem Code. Da sie native Python-Objekte zur Verfügung stellen, sind sie einfacher zu verwenden und zu verstehen.
- Anwendungsfälle für Protobuf-Nachrichten
- Protobufs eignen sich für leistungskritische Anwendungsfälle, insbesondere in Anwendungen, 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
.
Dynamisch geänderte Nachrichtentypen
Nachdem Sie den geeigneten Nachrichtentyp für Ihre Anwendung ausgewählt haben, müssen Sie möglicherweise den anderen Typ für einen bestimmten Workflow verwenden. In diesem Fall ist es einfach, mit den von der Clientbibliothek angebotenen Dienstprogrammen dynamisch zwischen den beiden Typen zu wechseln. Dieselbe Nachrichtenklasse Dog
wie oben verwenden:
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 der Protobuf-Nachrichtenoberfläche
Die Benutzeroberfläche von proto-Plus ist ausführlich dokumentiert. An dieser Stelle werden jedoch einige wichtige Unterschiede hervorgehoben, die sich auf häufige Anwendungsfälle der Google Ads-Clientbibliothek auswirken.
Byteserialisierung
- Proto-Plus-Nachrichten
serialized = type(campaign).serialize(campaign) deserialized = type(campaign).deserialize(serialized)
- Protokollpuffer-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)
- Protokollpuffer-Nachrichten
from google.protobuf.json_format import MessageToJson, Parse serialized = MessageToJson(campaign) deserialized = Parse(serialized, campaign)
Feldmasken
Die von api-core bereitgestellte Feldmasken-Hilfsmethode wurde für die Verwendung von protobuf-Nachrichteninstanzen entwickelt. Wenn Sie also proto-Plus-Nachrichten verwenden, konvertieren Sie diese in protobuf-Nachrichten, um den 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)
- Protokollpuffer-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 bereitgestellte Enums sind Instanzen des nativen Python-Typs enum
und übernehmen daher eine Reihe von praktischen Methoden.
Abrufen des Enum-Typs
Wenn Sie Enums mit der Methode GoogleAdsClient.get_type
abrufen, 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
- Protokollpuffer-Nachrichten
val = client.get_type("CampaignStatusEnum").PAUSED
Um das Abrufen von Enums zu vereinfachen, gibt es für GoogleAdsClient
-Instanzen ein praktisches Attribut, das unabhängig vom verwendeten Nachrichtentyp eine konsistente Schnittstelle hat:
val = client.enums.CampaignStatusEnum.PAUSED
Abrufen von Enum-Werten
Manchmal ist es hilfreich, den Wert oder die Feld-ID einer bestimmten Aufzählung zu kennen. Beispiel: PAUSED
auf dem 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)
- Protokollpuffer-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))
Abruf 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 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)
- Protokollpuffer-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, entsprechen wiederkehrende Felder im Allgemeinen typisierten Listen und verhalten sich somit fast identisch mit einer list
.
An wiederkehrende Skalarfelder anhängen
Wenn Sie wiederholten skalaren Typ-Feldern Werte hinzufügen, z. B. den Feldern string
oder int64
, ist die Schnittstelle unabhängig vom Nachrichtentyp dieselbe:
- Proto-Plus-Nachrichten
ad.final_urls.append("https://www.example.com")
- Protokollpuffer-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"])
- Protokollpuffer-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, verhält es sich beim Hinzufügen zu wiederkehrenden Feldern etwas anders:
- Proto-Plus-Nachrichten
frequency_cap = client.get_type("FrequencyCapEntry") frequency_cap.cap = 100 campaign.frequency_caps.append(frequency_cap)
- Protokollpuffer-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 unterschiedliche Weise Listen zuweisen:
- Proto-Plus-Nachrichten
# In proto-plus it's possible to use assignment. urls = ["https://www.example.com"] ad.final_urls = urls
- Protokollpuffer-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 simply check the message for # truthiness. is_empty = bool(campaign) is_empty = not campaign
- Protokollpuffer-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 GoogleAdsClient
:
client.copy_from(campaign, other_campaign)
Leere Nachrichtenfelder
Leere Nachrichtenfelder werden immer auf dieselbe Weise festgelegt, unabhängig vom verwendeten Nachrichtentyp. Sie müssen lediglich eine leere Nachricht in das entsprechende Feld kopieren. Weitere Informationen finden Sie im Abschnitt Nachrichtentext sowie im Leitfaden zu Leere Nachrichtenfelder. Hier ist 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 nachgestellten Unterstrich angezeigt, wenn der Name in Python auch ein reserviertes Wort 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. Sie kann auch programmatisch aufgerufen werden.
Installieren Sie zunächst das Modul:
python -m pip install gapic-generator
Führen Sie dann in einer Python-REPL oder einem -Skript folgende Schritte aus:
import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)
Feldpräsenz
Da die Felder von protobuf-Nachrichteninstanzen Standardwerte haben, lässt sich nicht immer intuitiv feststellen, ob ein Feld festgelegt wurde oder nicht.
- Proto-Plus-Nachrichten
# Use the "in" operator. has_field = "name" in campaign
- Protokollpuffer-Nachrichten
campaign = client.get_type("Campaign") # Determines whether "name" is set and not just an empty string. campaign.HasField("name")
Die protobuf-Klasse Message
hat eine HasField
-Methode, die bestimmt, ob das Feld in einer Nachricht festgelegt wurde, auch wenn es auf einen Standardwert festgelegt war.
Protokollzwischenspeicher-Nachrichtenmethoden
Die protobuf-Nachrichtenschnittstelle enthält einige praktische Methoden, die nicht Teil der proto-Plus-Schnittstelle sind. Der Zugriff auf sie ist jedoch einfach, indem eine proto-Plus-Nachricht in ihr protobuf-Gegenstück konvertiert wird:
# 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 Problemen bei der Migration zur Version 14.0.0
der Bibliothek hast, kannst du über unseren Tracker ein Problem melden.