Wiadomości protokołu Protobuf

W wersji 14.0.0 biblioteki klienta Pythona wprowadzono nowy wymagany parametr konfiguracji o nazwie use_proto_plus, który określa, czy biblioteka ma zwracać wiadomości protokołu Plus czy wiadomości protokołu. Szczegółowe informacje o ustawianiu tego parametru znajdziesz w dokumentacji konfiguracji.

W tej sekcji opisano wpływ na wydajność wyboru typów wiadomości, których chcesz używać. Dlatego zalecamy zapoznanie się z dostępnymi opcjami i podjęcie przemyślanej decyzji. Jeśli jednak chcesz uaktualnić ją do wersji 14.0.0 bez wprowadzania zmian w kodzie, możesz ustawić use_proto_plus na True, aby uniknąć zmian w interfejsie.

Komunikaty protokołu Plus a komunikaty protokołu protobuf

W wersji 10.0.0 biblioteka klienta Pythona została przeniesiona do nowego potoku generatora kodu, w którym zintegrowano protokół proto-plus, aby poprawić ergonomię interfejsu komunikatów protokołu Protobuf przez upodobnienie go do natywnych obiektów Pythona. Zaletą tego ulepszenia jest to, że proto+ wnosi większy nacisk na wydajność.

Skuteczność Protoplus

Jedną z głównych zalet protokołu Protoplus jest konwertowanie wiadomości protokołu i dobrze znanych typów na natywne typy Pythona z wykorzystaniem procesu zwanego strukturyzacją typów.

Organizowanie ma miejsce, gdy uzyskano dostęp do pola z instancji wiadomości protoplus, zwłaszcza gdy pole jest odczytywane lub ustawione, na przykład w definicji protokołu:

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 samo jak w przypadku każdego 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.

W analizie przeprowadzonej od momentu opublikowania wersji 10.0.0 ustaliliśmy, że czas poświęcony na konwersje tego typu ma wystarczająco duży wpływ na wydajność, aby użytkownicy mogli korzystać z wiadomości buforów protokołu.

Przypadki użycia wiadomości protokołu Proto+ i Protobuf

Przypadki użycia wiadomości Proto+
Proto+ 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.
Przypadki użycia wiadomości buforów protokołu
Z protokołów protobufs można korzystać w przypadkach użycia zainteresowanych wydajnością, zwłaszcza w aplikacjach, które muszą szybko przetwarzać duże raporty lub które tworzą żądania zmutowane przy użyciu dużej liczby operacji, np. przy użyciu BatchJobService lub OfflineUserDataJobService.

Dynamiczna zmiana typów wiadomości

Po wybraniu odpowiedniego typu wiadomości może się okazać, że w określonym przepływie pracy trzeba użyć innego typu. W takim przypadku łatwo jest przełączać się między tymi dwoma typami reklam za pomocą narzędzi dostępnych w bibliotece klienta. Użyj tej samej klasy wiadomości w polu 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 komunikatów buforów protokołu

Interfejs Proto+ jest szczegółowo udokumentowany, ale tutaj podkreślimy kilka najważniejszych 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)
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 pola

Metoda pomocnicza maski pola udostępniana przez interfejs api-core służy do korzystania z instancji komunikatów protokołu protobuf. Jeśli więc używasz wiadomości protobuf, przekonwertuj je na wiadomości protobuf, aby użyć funkcji pomocniczej:

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

Wyliczenia udostępniane przez wiadomości protokołu Plus są instancjami natywnego typu enum w Pythonie i dlatego dziedziczą różne wygodne metody.

Pobieranie typu wyliczenia

Gdy używasz metody GoogleAdsClient.get_type do pobierania wyliczeniowych, zwracane wiadomości różnią się nieco w zależności od tego, czy używasz wiadomości protoplus, czy 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 wyliczeniowych, w instancjach GoogleAdsClient dostępny jest atrybut wygodny, który ma spójny interfejs niezależnie od używanego typu wiadomości:

val = client.enums.CampaignStatusEnum.PAUSED

Pobieranie wartości wyliczenia

Czasami przydatna jest znajomość wartości lub identyfikatora pola danego wyliczenia, np. PAUSED w CampaignStatusEnum odpowiada wartości 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 enum

Czasami dobrze jest znać nazwę pola wyliczenia. Na przykład podczas odczytu obiektów z interfejsu API warto wiedzieć, któremu stanowi kampanii odpowiada integracja 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)
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 dokumentacji Proto-plus pola powtarzane są zasadniczo równoważne z listami typowymi, co oznacza, że działają prawie tak samo jak list.

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

Podczas dodawania wartości do powtarzających się pól typu skalarnego, np. 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")
Komunikaty Protobuf
ad.final_urls.append("https://www.example.com")

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

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

Jeśli pole powtarzane nie jest typem skalarnym, sposób dodawania ich do pól powtarzanych jest nieco inny:

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

Zarówno w przypadku skalarnych, jak i nieskalarnych pól powtarzanych możesz przypisać listy do tego 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
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 warto wiedzieć, czy wystąpienie wiadomości zawiera jakiekolwiek informacje lub czy ma ustawione któreś z swoich pól.

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
Komunikaty Protobuf
is_empty = campaign.ByteSize() == 0

Kopia wiadomości

W przypadku wiadomości protokołu protoplus i protokołu 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, jak ustawić puste pole wiadomości:

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

Nazwy pól będące zarezerwowanymi słowami

Gdy używasz wiadomości protoplus, nazwy pól automatycznie pojawiają się ze znakiem podkreślenia, jeśli dana nazwa jest też zarezerwowanym słowem w Pythonie. Oto przykład pracy z instancją Asset:

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

Pełna lista zarezerwowanych nazw jest tworzona w module generatora gapic. Dostęp do niego jest też możliwy automatycznie.

Najpierw zainstaluj moduł:

python -m pip install gapic-generator

Następnie w REPL lub skrypcie w Pythonie:

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

Obecność pól

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.

Wiadomości Proto Plus
# Use the "in" operator.
has_field = "name" in campaign
Komunikaty 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 ustawiono 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 migracją do wersji 14.0.0 biblioteki, zgłoś problem za pomocą naszego narzędzia do śledzenia.