Wiadomości protokołu Protobuf

Parametr konfiguracji use_proto_plus pozwala określić, czy biblioteka ma zwracać wiadomości proto-plus czy wiadomości protobuf. Szczegółowe informacje o tym, jak ustawić ten parametr, znajdziesz w dokumentacji dotyczącej konfiguracji.

Z tej sekcji dowiesz się, jak wybór typu wiadomości wpływa na skuteczność. Dlatego zalecamy zapoznanie się z dostępnymi opcjami, aby podjąć świadomą decyzję.

Porównanie wiadomości proto-plus i protobuf

Przepływ generowania kodu integruje proto-plus, aby poprawić ergonomię interfejsu wiadomości protobuf, sprawiając, że będą one zachowywać się bardziej jak natywne obiekty Pythona. Oznacza to jednak, że korzystanie z proto-plus powoduje wzrost obciążenia wydajności.

Skuteczność proto-plus

Jedną z głównych zalet proto-plus jest to, że konwertuje wiadomości proto-plusznane typy na natywne typy Pythona za pomocą procesu zwanego typem marshaling.

Marshalowanie występuje, gdy uzyskuje się dostęp do pola w przypadku wystąpienia wiadomości proto-plus, a w szczególności gdy pole jest odczytywane lub ustawiane, na przykład w definicji protobuf:

syntax = "proto3";

message Dog {
  string name = 1;
}

Gdy ta definicja zostanie przekonwertowana na klasę proto-plus, będzie wyglądać tak:

import proto

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

Następnie możesz zainicjować klasę Dog i uzyskać dostęp do jej pola name tak jak do dowolnego innego obiektu Pythona:

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

Podczas odczytywania i ustawiania pola name wartość jest konwertowana z natywnego typu str w Pythonie na typ string, aby była zgodna ze środowiskiem wykonawczym protobuf.

Na podstawie analizy wydajności stwierdziliśmy, że czas potrzebny na przeprowadzenie tego typu konwersji ma na tyle duży wpływ na wydajność, że użytkownicy powinni sami decydować, czy chcą używać wiadomości protobuf.

Przypadki użycia wiadomości protokołu protoplus i protobuf

Przypadki użycia wiadomości proto-plus
Protoplus oferuje wiele udoskonaleń w stosunku do wiadomości protobuf, dzięki czemu idealnie nadaje się do pisania łatwego w utrzymaniu i czytelnego kodu. Udostępniają natywne obiekty Pythona, więc są łatwiejsze w użyciu i zrozumieniu.
Zastosowania wiadomości Protobuf
Używaj protokołów protobuf w przypadkach, w których liczy się wydajność, zwłaszcza w aplikacjach, które muszą szybko przetwarzać duże raporty lub które tworzą zapytania o zmianę z dużą liczbą operacji, np. BatchJobService lub OfflineUserDataJobService.

Dynamiczna zmiana typów wiadomości

Po wybraniu odpowiedniego typu wiadomości dla aplikacji może się okazać, że w przypadku określonego procesu roboczego musisz użyć innego typu. W tym przypadku można łatwo przełączać się między tymi dwoma typami dynamicznie, korzystając z narzędzi oferowanych przez bibliotekę klienta. Przy użyciu tej samej klasy wiadomości Dog z powyższego przykładu:

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)

Różnice w interfejsie wiadomości Protobuf

Interfejs proto-plus jest szczegółowo opisany, ale tutaj wyróżniliśmy kilka kluczowych różnic, które mają wpływ na typowe zastosowania biblioteki klienta Google Ads.

Serializacja bajtów

Komunikaty proto-plus
serialized = type(campaign).serialize(campaign)
deserialized = type(campaign).deserialize(serialized)
komunikaty Protobuf;
serialized = campaign.SerializeToString()
deserialized = campaign.FromString(serialized)

Serializacja JSON

Wiadomości Proto Plus
serialized = type(campaign).to_json(campaign)
deserialized = type(campaign).from_json(serialized)
Komunikaty Protobuf
from google.protobuf.json_format import MessageToJson, Parse

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

Maski pól

Metoda pomocnicza maski pola udostępniana przez api-core jest przeznaczona do używania instancji wiadomości protobuf. Jeśli więc używasz wiadomości protobuf, przekonwertuj je na wiadomości protobuf, aby użyć funkcji pomocniczej:

Komunikaty proto-plus
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)
komunikaty Protobuf;
from google.api_core.protobuf_helpers import field_mask

campaign = client.get_type("Campaign")
mask = field_mask(None, campaign)

Wartości w polu enum

Enumy udostępniane przez wiadomości proto-plus są instancjami natywnego typu Pythona enum, a zatem dziedziczą wiele metod ułatwiających pracę.

Pobieranie typu wyliczeniowego

Gdy używasz metody GoogleAdsClient.get_type do pobierania typów enumeracji, zwracane komunikaty różnią się nieco w zależności od tego, czy używasz proto-plus czy komunikatów protobuf. Na przykład:

Wiadomości Proto Plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
komunikaty Protobuf;
val = client.get_type("CampaignStatusEnum").PAUSED

Aby ułatwić pobieranie typów, w przypadku instancji GoogleAdsClient jest dostępny atrybuty ułatwiający, który ma spójny interfejs niezależnie od tego, którego typu wiadomości używasz:

val = client.enums.CampaignStatusEnum.PAUSED

Pobieranie wartości typu wyliczeniowego

Czasami przydatna jest wartość lub identyfikator pola danego wyliczenia. Na przykład PAUSED w polu CampaignStatusEnum odpowiada 3:

Wiadomości Proto Plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the value of campaign status
print(campaign.status.value)
Komunikaty Protobuf
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))

Pobieranie nazwy typu wyliczeniowego

Czasami warto znać nazwę pola typu enum. Na przykład podczas odczytywania obiektów z interfejsu API możesz chcieć wiedzieć, któremu stanowi kampanii odpowiada wartość int 3:

Komunikaty proto-plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the name of campaign status
print(campaign.status.name)
Komunikaty Protobuf
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)

Pola powtarzane

Zgodnie z opisem w dokumentach Proto-plus pola powtarzane są zasadniczo równoważne z listami typowymi, co oznacza, że działają prawie tak samo jak list.

Dołączanie wartości do powtarzających się pól skalarnych

Podczas dodawania wartości do powtarzanych pól skalowania, np. pól string lub int64, interfejs jest taki sam niezależnie od typu wiadomości:

Komunikaty proto-plus
ad.final_urls.append("https://www.example.com")
Komunikaty Protobuf
ad.final_urls.append("https://www.example.com")

Obejmuje to również wszystkie inne popularne metody list, np. extend:

Komunikaty proto-plus
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
komunikaty Protobuf;
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])

Dołączanie typów wiadomości do pól powtarzalnych

Jeśli powtarzane pole nie jest polem typu skalarnego, jego dodawanie do powtarzanych pól działa nieco inaczej:

Komunikaty proto-plus
frequency_cap = client.get_type("FrequencyCapEntry")
frequency_cap.cap = 100
campaign.frequency_caps.append(frequency_cap)
komunikaty Protobuf;
# The add method initializes a message and adds it to the repeated field
frequency_cap = campaign.frequency_caps.add()
frequency_cap.cap = 100

Przypisywanie pól powtarzalnych

W przypadku zarówno skalarnych, jak i nieskalarnych pól powtarzalnych możesz przypisywać do nich listy na różne sposoby:

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

puste wiadomości;

Czasami przydaje się wiedzieć, czy instancja wiadomości zawiera jakieś informacje lub czy ma ustawione jakieś pola.

Komunikaty proto-plus
# When using proto-plus messages you can simply check the message for
# truthiness.
is_empty = bool(campaign)
is_empty = not campaign
komunikaty protokołu protobuf;
is_empty = campaign.ByteSize() == 0

Treść wiadomości

W przypadku wiadomości proto-plus i protobuf zalecamy użycie metody pomocniczej copy_from w GoogleAdsClient:

client.copy_from(campaign, other_campaign)

Puste pola wiadomości

Proces ustawiania pustych pól wiadomości jest taki sam niezależnie od używanego typu wiadomości. Wystarczy skopiować pustą wiadomość w odpowiednim polu. Zobacz sekcję Kopia wiadomości oraz przewodnik Puste pola wiadomości. Oto przykład ustawienia pustego pola wiadomości:

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

nazwy pól, które są zastrzeżonymi słowami;

W przypadku wiadomości proto-plus nazwy pól są automatycznie wyświetlane z podkreśleniem, jeśli są one również zarezerwowanymi słowami w Pythonie. Oto przykład pracy z instancją Asset:

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

Pełna lista nazw zastrzeżonych jest tworzona w module gapicgenerator. Dostęp do niego można uzyskać automatycznie.

Najpierw zainstaluj moduł:

python -m pip install gapic-generator

Następnie w replu lub skrypcie Pythona:

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

Obecność w polu

Ponieważ pola instancji wiadomości buforów protokołu mają wartości domyślne, ustalenie, czy pole zostało ustawione, czy nie zawsze jest intuicyjne.

Komunikaty proto-plus
# Use the "in" operator.
has_field = "name" in campaign
komunikaty protokołu protobuf;
campaign = client.get_type("Campaign")
# Determines whether "name" is set and not just an empty string.
campaign.HasField("name")

Interfejs klasy protobufMessage ma metodę HasField, która określa, czy pole w wiadomości zostało ustawione, nawet jeśli ma wartość domyślną.

Metody komunikatów buforów protokołu

Interfejs wiadomości protobuf zawiera pewne wygodne metody, które nie są częścią interfejsu protobuf. Można je jednak łatwo uzyskać, konwertując wiadomość proto-plus na jej odpowiednik w formacie protobuf:

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

Śledzenie problemów

Jeśli masz pytania dotyczące tych zmian lub problemy z przeniesieniem do najnowszej wersji biblioteki, zgłoś problem w naszym systemie śledzenia błędów.