Wiadomości protobuf

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Wersja 14.0.0 biblioteki klienta w Pythonie wprowadza nowy wymagany parametr konfiguracji o nazwie use_proto_plus. Określa on, czy biblioteka ma zwracać wiadomości protobuf czy wiadomości protobuf. Szczegółowe informacje o tym, jak ustawić ten parametr, znajdziesz w dokumentacji konfiguracji.

Aby móc podejmować lepsze decyzje, zapoznaj się z informacjami o tych typach wiadomości. Zalecamy więc zapoznanie się z tymi opcjami. Jeśli jednak chcesz przejść na wersję 14.0.0 bez wprowadzania zmian w kodzie, możesz ustawić use_proto_plus na True, aby uniknąć zmian interfejsu.

Komunikaty protoplus i protobuf

W wersji 10.0.0 biblioteka klienta w języku Python została przeniesiona do nowego potoku generatora kodu, który zintegrował proto-plus z myślą o poprawie ergonomiki interfejsu wiadomości protobuf przez zachowanie ich jako natywnych obiektów w Pythonie. Kompensacja tego wzrostu polega na tym, że proto-Plus zwiększa nakład pracy.

Skuteczność proto-plus

Jedną z głównych zalet protokołu proto-plus jest przekształcanie komunikatów protobuf i dobrze znanych typów w natywne typy Pythona w ramach procesu o nazwie typ Marshal.

Halhaling ma miejsce, gdy dostęp do pola uzyskuje się w instancji komunikatu proto-plus, zwłaszcza w przypadku odczytania lub ustawienia pola, na przykład w definicji protobuf:

syntax = "proto3";

message Dog {
  string name = 1;
}

Po przekonwertowaniu na klasę protoplus będzie wyglądać mniej więcej tak:

import proto

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

Następnie zainicjuj klasę Dog i uzyskaj dostęp do jej pola name tak jak w przypadku każdego innego obiektu w Pythonie:

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

Podczas odczytywania i ustawiania pola name wartość jest konwertowana z natywnego typu Python str na typ string, dzięki czemu wartość jest zgodna ze środowiskiem wykonawczym protobuf.

Z analizy przeprowadzonej przez nas w wersji 10.0.0 wynika, że czas spędzony na konwersjach tego typu ma wystarczająco duży wpływ na wydajność, więc dać użytkownikom możliwość korzystania z protobufów.

Przypadki użycia wiadomości protoplus i protobuf

Przypadki użycia wiadomości „Proto-plus”
Proto-plus oferuje liczne ergonomiczne ulepszenia w porównaniu z wiadomościami protobuf, dlatego są one idealne do tworzenia czytelnego i czytelnego kodu. Ponieważ udostępniają one natywne obiekty Pythona, są łatwiejsze w użyciu i zrozumiałe.
Przypadki użycia wiadomości Protobuf
Protobufy sprawdzają się w przypadkach użycia związanych z wydajnością, zwłaszcza w aplikacjach, które muszą szybko przetwarzać duże raporty lub gdy zmieniają żądania, co wiąże się z dużą liczbą operacji, na przykład za pomocą BatchJobService lub OfflineUserDataJobService.

Dynamicznie zmieniające typy wiadomości

Po wybraniu odpowiedniego typu wiadomości dla swojej aplikacji może się okazać, że musisz użyć innego typu wiadomości do danego procesu. W takim przypadku można łatwo przełączać się między tymi 2 typami za pomocą narzędzi dostępnych w bibliotece klienta. Używanie powyższej klasy wiadomości Dog:

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 protokołu Protobuf

Interfejs proto-plus jest szczegółowy, ale opisujemy tutaj kilka kluczowych różnic, które wpływają na typowe przypadki użycia biblioteki klienta Google Ads.

Serializacja bajtów

Wiadomości Proto-Plus
serialized = type(campaign).serialize(campaign)
deserialized = type(campaign).deserialize(serialized)
Wiadomości Protobuf
serialized = campaign.SerializeToString()
deserialized = campaign.FromString(serialized)

Seria w formacie JSON

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

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

Maski pól

Metoda pomocnicza maski pola udostępniona przez api-core jest przeznaczona do używania instancji wiadomości protobuf. Jeśli korzystasz z wiadomości protoplus, przekonwertuj je na wiadomości protobuf, aby użyć pomocnika:

Wiadomości 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)
Wiadomości 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

Wyrażenia widoczne w wiadomościach protoplus są wystąpieniami natywnego języka Python o nazwie enum, więc dziedziczą różne metody wygodnych.

Pobieranie typów enum

Używając metody GoogleAdsClient.get_type do pobierania wartości wyliczeniowych, zwracane wiadomości różnią się nieznacznie w zależności od tego, czy używasz wiadomości proto-plus czy protobuf. Przykład:

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

Aby ułatwić wyliczenie, na stronach GoogleAdsClient, które mają spójny interfejs niezależnie od używanego typu wiadomości, dostępny jest atrybut wygodny dla:

val = client.enums.CampaignStatusEnum.PAUSED

Pobieranie wartości numm

Czasami warto znać wartość lub identyfikator pola danego wyliczenia, np. 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)
Wiadomości 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 Enum

Czasami warto znać nazwę pola enum. Na przykład podczas odczytywania obiektów z interfejsu API chcesz wiedzieć, do którego stanu kampanii odnosi się reguła 3.

Wiadomości Proto-Plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the name of campaign status
print(campaign.status.name)
Wiadomości 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 dokumentacją proto-plus pola powtarzane są zasadniczo równoważne z listami wpisywanymi, co oznacza, że działają prawie tak samo jak list.

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

W przypadku dodawania wartości do powtarzających się pól skalowania, na przykład pól string lub int64, interfejs jest taki sam niezależnie od typu wiadomości:

Wiadomości Proto-Plus
ad.final_urls.append("https://www.example.com")
Wiadomości Protobuf
ad.final_urls.append("https://www.example.com")

Obejmuje to też wszystkie inne popularne metody list, np. extend:

Wiadomości Proto-Plus
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
Wiadomości Protobuf
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])

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

Jeśli pole powtarzane nie jest typem skalującym, zachowanie podczas dodawania go do pól powtarzających się trochę różni:

Wiadomości Proto-Plus
frequency_cap = client.get_type("FrequencyCapEntry")
frequency_cap.cap = 100
campaign.frequency_caps.append(frequency_cap)
Wiadomości 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 powtarzanych

W przypadku pól skalarnych i nieskalowanych możesz przypisywać listy do pola 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
Wiadomości 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 dobrze jest sprawdzić, czy instancja wiadomości zawiera jakiekolwiek informacje lub czy ma ustawione dowolne pole.

Wiadomości Proto-Plus
# When using proto-plus messages you can simply check the message for
# truthiness.
is_empty = bool(campaign)
is_empty = not campaign
Wiadomości Protobuf
is_empty = campaign.ByteSize() == 0

Kopia wiadomości

W przypadku wiadomości protoplus i protobuf zalecamy korzystanie z metody pomocniczej copy_from na stronie GoogleAdsClient:

client.copy_from(campaign, other_campaign)

Puste pola wiadomości

Proces ustawiania pustych pól wiadomości jest taki sam niezależnie od typu wiadomości, której używasz. Wystarczy, że skopiujesz pustą wiadomość do odpowiedniego pola. Zobacz sekcję Kopia wiadomości i przewodnik po pustych polach wiadomości. Oto przykład, jak ustawić puste pole wiadomości:

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

Nazwy pól zastrzeżone

Jeśli korzystasz z wiadomości protoplus, nazwy pól automatycznie wyświetlają się z podkreśleniem, jeśli nazwa jest również zarezerwowanym słowem w Pythonie. Oto przykład pracy z instancją Asset:

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

Pełną listę zarezerwowanych nazw tworzy się w module generatora grafu internetowego. Dostęp do nich można też uzyskiwać automatycznie.

Najpierw zainstaluj moduł:

python -m pip install gapic-generator

Następnie w skrypcie REPL lub w Pythonie:

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

obecnością w polu,

Pola w instancjach protobuf mają wartości domyślne, dlatego nie zawsze są intuicyjne i nie wiadomo, czy pole zostało ustawione.

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

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

Metody wiadomości protobuf

Interfejs protobuf zawiera kilka wygodnych metod, które nie są częścią interfejsu protoplus, ale są łatwo dostępne przez przekonwertowanie wiadomości protobuf na odpowiedni odpowiednik 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 problemów z przejściem na 14.0.0 w bibliotece, zgłoś problem na naszym trackerze.