Versão
14.0.0
da biblioteca de cliente Python apresenta um novo parâmetro de configuração obrigatório
chamado use_proto_plus
, que especifica se você quer que a biblioteca retorne
mensagens proto-plus ou
Mensagens protobuf. Para detalhes sobre
como definir esse parâmetro, consulte os documentos de configuração.
Esta seção descreve as implicações de desempenho de escolher quais tipos de
mensagens, portanto, recomendamos que você leia e entenda
as opções para tomar uma decisão informada. No entanto, se você quiser
atualizar para a versão 14.0.0
sem fazer alterações no código,
use_proto_plus
para True
para evitar interrupções interruptivas da interface.
Mensagens Proto-plus versus protobuf
Na versão 10.0.0
, a biblioteca de cliente Python migrou para um novo gerador de código
um pipeline que integrou
proto-plus como uma forma de melhorar
a ergonomia da interface de mensagens protobuf, fazendo com que elas se comportem mais
como objetos nativos do Python. A desvantagem dessa melhoria é que o proto-plus
introduz sobrecarga de desempenho.
Desempenho de proto-plus
Um dos principais benefícios do proto-plus é que ele converte protobufs mensagens e tipos conhecidos para tipos Python nativos por um processo chamado type marshaling.
O marshaling ocorre quando um campo é acessado em uma instância de mensagem proto-plus, especificamente quando um campo é lido ou definido, por exemplo, em um protobuf definição:
syntax = "proto3";
message Dog {
string name = 1;
}
Quando essa definição é convertida em uma classe proto-plus, ela ficaria algo assim:
import proto
class Dog(proto.Message):
name = proto.Field(proto.STRING, number=1)
Em seguida, você pode inicializar a classe Dog
e acessar o campo name
como faria
qualquer outro objeto Python:
dog = Dog()
dog.name = "Scruffy"
print(dog.name)
Ao ler e definir o campo name
, o valor é convertido de um arquivo nativo
tipo str
do Python para um tipo string
, ou seja,
se o valor é compatível com o ambiente de execução do protobuf.
Na análise que realizamos desde o lançamento da versão 10.0.0
,
determinou que o tempo gasto nesses tipos de conversão é suficiente
no desempenho. É importante dar aos usuários a opção de usar protobufs
e envio de mensagens.
Casos de uso de mensagens proto-plus e protobuf
- Casos de uso de mensagens Proto-plus
- O Protoplus oferece várias melhorias ergonômicas em relação às mensagens protobuf, portanto, são ideais para escrever códigos de fácil manutenção e leitura. Como eles expõem objetos nativos do Python, eles são mais fáceis de usar e entender.
- Casos de uso de mensagens do protobuf
- Use protobufs para casos de uso sensíveis ao desempenho, especificamente em apps
que precisam processar relatórios grandes rapidamente ou que criam solicitações mutate com uma
um grande número de operações, por exemplo, com
BatchJobService
ouOfflineUserDataJobService
Como alterar dinamicamente os tipos de mensagens
Depois de selecionar o tipo de mensagem apropriado para seu app, você poderá
que você precisa usar o outro tipo para um fluxo de trabalho específico. Nesse caso,
fácil alternar dinamicamente entre os dois tipos usando utilitários oferecidos pelo
biblioteca de cliente. Use a mesma classe de mensagem Dog
mostrada acima:
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)
Diferenças na interface de mensagens do protobuf
A interface proto-plus está documentada em detalhes, mas aqui vamos destacar algumas diferenças importantes que afetam casos de uso comuns do cliente do Google Ads biblioteca.
Serialização de bytes
- Mensagens proto-plus
serialized = type(campaign).serialize(campaign) deserialized = type(campaign).deserialize(serialized)
- Mensagens do protobuf
serialized = campaign.SerializeToString() deserialized = campaign.FromString(serialized)
Serialização JSON
- Mensagens proto-plus
serialized = type(campaign).to_json(campaign) deserialized = type(campaign).from_json(serialized)
- Mensagens do protobuf
from google.protobuf.json_format import MessageToJson, Parse serialized = MessageToJson(campaign) deserialized = Parse(serialized, campaign)
Máscaras de campo
O método auxiliar da máscara de campo fornecido pelo api-core foi projetado para usar protobuf instâncias de mensagens. Portanto, ao usar mensagens proto-plus, converta-as em protobuf mensagens para utilizar o assistente:
- Mensagens 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)
- Mensagens do protobuf
from google.api_core.protobuf_helpers import field_mask campaign = client.get_type("Campaign") mask = field_mask(None, campaign)
Enums
Os tipos enumerados expostos por mensagens proto-plus são instâncias das classes nativas
enum
. Portanto,
herdam vários métodos de conveniência.
Recuperação do tipo de enumeração
Ao usar o método GoogleAdsClient.get_type
para recuperar tipos enumerados, as mensagens
retornados são ligeiramente diferentes, dependendo se você usa
proto-plus ou protobuf. Exemplo:
- Mensagens proto-plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
- Mensagens do protobuf
val = client.get_type("CampaignStatusEnum").PAUSED
Para facilitar a recuperação de tipos enumerados, há um atributo de conveniência no
instâncias de GoogleAdsClient
que têm uma interface consistente, independentemente de qual
tipo de mensagem que você está usando:
val = client.enums.CampaignStatusEnum.PAUSED
Recuperação de valor de enumeração
Às vezes, é útil saber o valor, ou ID de campo, de um determinado tipo enumerado, para
Por exemplo, PAUSED
em CampaignStatusEnum
corresponde a 3
:
- Mensagens proto-plus
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the value of campaign status print(campaign.status.value)
- Mensagens do 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))
Recuperação de nome de enumeração
Às vezes, é útil saber o nome de um campo de enumeração. Por exemplo, quando
da API, convém saber qual status da campanha o
int 3
corresponde a:
- Mensagens proto-plus
campaign = client.get_type("Campaign") campaign.status = client.enums.CampaignStatusEnum.PAUSED # To read the name of campaign status print(campaign.status.name)
- Mensagens do 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)
Campos repetidos
Como descrito no proto-plus
docs,
campos repetidos geralmente são equivalentes a listas digitadas, o que significa que eles
se comportam de maneira quase idêntica a uma list
.
Anexação a campos escalares repetidos
Ao adicionar valores a objetos escalares repetidos,
type, por exemplo
nos campos string
ou int64
, a interface é a mesma, independente da mensagem
type
- Mensagens proto-plus
ad.final_urls.append("https://www.example.com")
- Mensagens do protobuf
ad.final_urls.append("https://www.example.com")
Isso também inclui todos os outros métodos list
comuns, por exemplo, extend
:
- Mensagens proto-plus
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
- Mensagens do protobuf
ad.final_urls.extend(["https://www.example.com", "https://www.example.com/2"])
Como anexar tipos de mensagens a campos repetidos
Se o campo repetido não for um escalar type, o comportamento ao adicioná-los ao repetidos é um pouco diferente:
- Mensagens proto-plus
frequency_cap = client.get_type("FrequencyCapEntry") frequency_cap.cap = 100 campaign.frequency_caps.append(frequency_cap)
- Mensagens do protobuf
# The add method initializes a message and adds it to the repeated field frequency_cap = campaign.frequency_caps.add() frequency_cap.cap = 100
Atribuição de campos repetidos
Para campos repetidos escalares e não escalares, é possível atribuir listas ao de várias maneiras:
- Mensagens proto-plus
# In proto-plus it's possible to use assignment. urls = ["https://www.example.com"] ad.final_urls = urls
- Mensagens do 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
Mensagens vazias
Às vezes, é útil saber se uma instância de mensagem contém informações ou tem qualquer um dos campos definidos.
- Mensagens proto-plus
# When using proto-plus messages you can simply check the message for # truthiness. is_empty = bool(campaign) is_empty = not campaign
- Mensagens do protobuf
is_empty = campaign.ByteSize() == 0
Texto da mensagem
Para mensagens proto-plus e protobuf, recomendamos o uso do copy_from
método auxiliar em GoogleAdsClient
:
client.copy_from(campaign, other_campaign)
Campos de mensagem vazios
O processo de definição de campos de mensagem vazios é o mesmo, independentemente da tipo de mensagem que você está usando. Você só precisa copiar uma mensagem vazia no campo em questão. Consulte a seção Cópia da mensagem e a seção Mensagem vazia Campos. Aqui está um exemplo de como para definir um campo de mensagem vazio:
client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))
Nomes de campos que são palavras reservadas
Ao usar mensagens proto-plus, os nomes dos campos aparecem automaticamente com uma
sublinhado à direita se o nome também for uma palavra reservada em Python. Este é um
Exemplo de trabalho com uma instância do Asset
:
asset = client.get_type("Asset")
asset.type_ = client.enums.AssetTypeEnum.IMAGE
A lista completa de consultas nomes é construída no nível generator. Pode ser com acesso programático.
Primeiro, instale o módulo:
python -m pip install gapic-generator
Em seguida, em um script REPL ou Python:
import gapic.utils
print(gapic.utils.reserved_names.RESERVED_NAMES)
Presença de campo
Como os campos em instâncias de mensagens protobuf têm valores padrão, não é sempre intuitivo saber se um campo foi definido ou não.
- Mensagens proto-plus
# Use the "in" operator. has_field = "name" in campaign
- Mensagens do protobuf
campaign = client.get_type("Campaign") # Determines whether "name" is set and not just an empty string. campaign.HasField("name")
O protobuf
Message
interface de classe tem um método HasField
que determina se o campo em uma
for definida, mesmo com um valor padrão.
Métodos de mensagem protobuf
A interface de mensagens protobuf inclui alguns métodos de conveniência que não são parte da interface proto-plus, No entanto, é simples acessá-los convertendo uma mensagem proto-plus na contraparte 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())
Issue tracker
Se você tiver dúvidas sobre essas mudanças ou problemas na migração para
versão 14.0.0
da biblioteca, registre uma
problema no nosso
rastreador.