پیام‌های Protobuf

با پارامتر پیکربندی use_proto_plus، می‌توانید مشخص کنید که می‌خواهید کتابخانه پیام‌های proto-plus یا پیام‌های protobuf را برگرداند. برای جزئیات مربوط به نحوه تنظیم این پارامتر، اسناد پیکربندی را ببینید.

این بخش پیامدهای عملکردی هر گزینه را شرح می‌دهد تا بتوانید بهترین رویکرد را برای برنامه‌تان انتخاب کنید.

پیام‌های Proto-plus درمقابل protobuf

خط لوله تولیدکننده کد proto-plus را ادغام می‌کند تا ارگونومی میانای پیام protobuf را با شبیه‌تر کردن رفتار آن‌ها به اشیای استاندارد Python بهبود بخشد. بااین‌حال، این یعنی استفاده از proto-plus سربار عملکرد ایجاد می‌کند.

عملکرد Proto-plus

یکی از مزایای اصلی proto-plus این است که پیام‌های protobuf و انواع شناخته‌شده را ازطریق فرایندی به‌نام مرتب‌سازی نوع به انواع Python داخلی تبدیل می‌کند.

مرتب‌سازی زمانی اتفاق می‌افتد که به فیلدی در نمونه پیام proto-plus دسترسی پیدا شود، به‌ویژه زمانی که فیلدی خوانده یا تنظیم شود، برای مثال، در تعریف protobuf:

syntax = "proto3";

message Dog {
  string name = 1;
}

وقتی این تعریف به کلاس proto-plus تبدیل می‌شود، به این شکل است:

import proto


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

سپس می‌توانید کلاس Dog را مقداردهی اولیه کنید و به فیلد name آن دسترسی پیدا کنید، درست مانند هر شیء Python دیگری:

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

هنگام خواندن و تنظیم فیلد name، مقدار از نوع توکار Python str به نوع string تبدیل می‌شود تا مقدار با زمان اجرای protobuf سازگار باشد.

زمان صرف‌شده برای انجام این تبدیل‌های نوع تأثیر عملکردی به‌اندازه کافی بزرگی دارد که باید براساس نیازهای برنامه‌تان تصمیم بگیرید که از پیام‌های proto-plus یا protobuf استفاده کنید یا نه.

موارد استفاده برای پیام‌های proto-plus و protobuf

موارد استفاده از پیام Proto-plus
Proto-plus تعدادی بهبود ارگونومیک نسبت‌به پیام‌های protobuf ارائه می‌دهد، بنابراین برای نوشتن کد قابل‌نگهداری و خوانا ایده‌آل هستند. ازآنجایی‌که این مدل‌ها اشیاء استاندارد Python را نمایش می‌دهند، استفاده و درک آن‌ها آسان‌تر است.
موارد استفاده پیام Protobuf
از protobufs برای موارد استفاده حساس به عملکرد استفاده کنید، به‌ویژه در برنامه‌هایی که باید گزارش‌های بزرگ را به‌سرعت پردازش کنند، یا درخواست‌های تغییر را با تعداد زیادی عملیات بسازند، برای مثال با BatchJobService یا OfflineUserDataJobService.

جابه‌جایی پویا بین انواع پیام

پس‌از انتخاب نوع پیام مناسب برای برنامه‌تان، ممکن است متوجه شوید که باید از نوع دیگر برای گردش کار خاصی استفاده کنید. دراین‌صورت، می‌توانید بااستفاده از ابزارهای ارائه‌شده توسط کتابخانه مشتری، به‌طور پویا بین دو نوع جابه‌جا شوید. بااستفاده از همان کلاس پیام 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)

تفاوت‌های میانای پیام Protobuf

میانای proto-plus با جزئیات مستند شده است، و بخش‌های زیر تفاوت‌های کلیدی را که بر موارد استفاده رایج برای کتابخانه مشتری Google Ads تأثیر می‌گذارند برجسته می‌کنند.

سریال‌سازی بایت‌ها

پیام‌های Proto-plus
serialized = type(campaign).serialize(campaign)
deserialized = type(campaign).deserialize(serialized)
پیام‌های Protobuf
serialized = campaign.SerializeToString()
deserialized = campaign.FromString(serialized)

سریال‌سازی JSON

پیام‌های Proto-plus
serialized = type(campaign).to_json(campaign)
deserialized = type(campaign).from_json(serialized)
پیام‌های Protobuf
from google.protobuf.json_format import MessageToJson, Parse

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

ماسک‌های فیلد

روش کمکی پوشش فیلد ارائه‌شده توسط api-core برای استفاده از نمونه‌های پیام protobuf طراحی شده است. هنگام استفاده از پیام‌های proto-plus، آن‌ها را به پیام‌های protobuf تبدیل کنید تا از کمک‌کننده استفاده کنید:

پیام‌های 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)
پیام‌های Protobuf
from google.api_core.protobuf_helpers import field_mask

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

شمارشی‌ها

Enums exposed by proto-plus messages are instances of Python's built-in enum type and therefore inherit a number of convenience methods.

بازیابی نوع شمارشی

هنگام استفاده از روش GoogleAdsClient.get_type برای بازیابی شمارشی‌ها، پیام‌هایی که برگردانده می‌شوند بسته به اینکه از پیام‌های proto-plus یا protobuf استفاده می‌کنید کمی متفاوت هستند. برای مثال:

پیام‌های Proto-plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
پیام‌های Protobuf
val = client.get_type("CampaignStatusEnum").PAUSED

برای ساده‌تر کردن بازیابی شمارش‌ها، یک مشخصه راحتی در نمونه‌های GoogleAdsClient وجود دارد که صرف‌نظر از نوع پیامی که استفاده می‌کنید، میانای ثابتی دارد:

val = client.enums.CampaignStatusEnum.PAUSED

بازیابی مقدار Enum

گاهی اوقات دانستن مقدار یا شناسه فیلد یک enum خاص مفید است، برای مثال، PAUSED در CampaignStatusEnum با 3 مطابقت دارد:

پیام‌های Proto-plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the value of campaign status
print(campaign.status.value)
پیام‌های Protobuf
campaign = client.get_type("Campaign")
status_enum = client.enums.CampaignStatusEnum
campaign.status = status_enum.PAUSED
# Native protobuf enum fields already store the integer value (3):
print(campaign.status)
# Or look up the integer value from the enum name string:
print(status_enum.CampaignStatus.Value("PAUSED"))

بازیابی نام شمارشی

گاهی اوقات دانستن نام فیلد enum مفید است. برای مثال، هنگام خواندن اشیا از میانای برنامه‌سازی کاربردی، ممکن است بخواهید بدانید عدد صحیح 3 با کدام وضعیت پویش مطابقت دارد:

پیام‌های Proto-plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the name of campaign status
print(campaign.status.name)
پیام‌های 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
print(status_enum.CampaignStatus.Name(campaign.status))

فیلدهای تکراری

همان‌طور که در اسناد proto-plus شرح داده شده است، فیلدهای تکراری عموماً معادل فهرست‌های تایپ‌شده هستند، یعنی تقریباً رفتاری مشابه با list دارند.

افزودن مقادیر به فیلدهای اسکالر تکراری

هنگام افزودن مقادیر به فیلدهای تکراری نوع اسکالر، برای مثال فیلدهای string یا int64، رابط کاربری بدون توجه به نوع پیام یکسان است:

پیام‌های Proto-plus
ad.final_urls.append("https://www.example.com")
پیام‌های Protobuf
ad.final_urls.append("https://www.example.com")

این شامل همه روش‌های رایج دیگر list نیز می‌شود، برای مثال extend:

پیام‌های Proto-plus
ad.final_urls.extend(
    ["https://www.example.com", "https://www.example.com/2"]
)
پیام‌های Protobuf
ad.final_urls.extend(
    ["https://www.example.com", "https://www.example.com/2"]
)

افزودن انواع پیام به فیلدهای تکراری

اگر فیلد تکراری از نوع اسکالر نباشد، رفتار هنگام افزودن آن‌ها به فیلدهای تکراری کمی متفاوت است:

پیام‌های Proto-plus
frequency_cap = client.get_type("FrequencyCapEntry")
frequency_cap.cap = 100
campaign.frequency_caps.append(frequency_cap)
پیام‌های Protobuf
# The add method initializes a message and adds it to the repeated field
frequency_cap = campaign.frequency_caps.add()
frequency_cap.cap = 100

اختصاص دادن فیلدهای تکراری

برای فیلدهای تکراری اسکالر و غیراسکالر، می‌توانید فهرست‌ها را به روش‌های مختلفی به فیلد اختصاص دهید:

پیام‌های Proto-plus
# In proto-plus it's possible to use assignment.
urls = ["https://www.example.com"]
ad.final_urls = urls
پیام‌های 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

پیام‌های خالی

گاهی اوقات مفید است که بدانید آیا نمونه پیام حاوی اطلاعاتی است یا اینکه فیلدهای آن تنظیم شده‌اند یا نه.

پیام‌های Proto-plus
# When using proto-plus messages you can check the message for truthiness.
is_empty = not bool(campaign)
پیام‌های Protobuf
is_empty = campaign.ByteSize() == 0

کپی پیام

برای هر دو پیام proto-plus و protobuf، از روش کمکی copy_from در GoogleAdsClient استفاده کنید:

client.copy_from(campaign, other_campaign)

فیلدهای پیام خالی است

فرایند تنظیم فیلدهای پیام خالی صرف‌نظر از نوع پیامی که استفاده می‌کنید یکسان است. پیام خالی را در فیلد موردنظر کپی کنید. بخش کپی پیام و همچنین راهنمای فیلدهای پیام خالی را ببینید. مثال زیر نشان می‌دهد چگونه فیلد پیام خالی تنظیم کنید:

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

نام‌های فیلدی که واژه‌های رزروشده هستند

هنگام استفاده از پیام‌های proto-plus، اگر نام فیلد کلمه‌ای رزروشده در Python نیز باشد، نام‌های فیلد به‌طور خودکار با زیرخط دنباله‌دار نشان داده می‌شوند. مثال زیر نحوه کار با نمونه Asset را نشان می‌دهد:

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

فهرست کامل نام‌های رزروشده در ماژول gapic generator ساخته می‌شود. همچنین می‌توان به‌صورت برنامه‌نویسی‌شده به آن دسترسی داشت.

ابتدا واحد را نصب کنید:

python -m pip install gapic-generator

سپس، در یک REPL یا اسکریپت Python:

import gapic.utils

print(gapic.utils.reserved_names.RESERVED_NAMES)

حضور در محل

ازآنجایی‌که فیلدهای نمونه‌های پیام protobuf دارای مقادیر پیش‌فرض هستند، همیشه نمی‌توان به‌راحتی تشخیص داد که آیا فیلدی تنظیم شده است یا نه.

پیام‌های Proto-plus
# Use the "in" operator.
has_field = "name" in campaign
پیام‌های Protobuf
campaign = client.get_type("Campaign")
# Determines whether "name" is set and not just an empty string.
campaign.HasField("name")

میانای کلاس protobuf Message دارای روش HasField است که تعیین می‌کند آیا زیرپیام، فیلد oneof، یا فیلد اسکالر optional در پیام تنظیم شده است یا نه، حتی اگر روی مقدار پیش‌فرض تنظیم شده باشد. (فراخوانی HasField در فیلدهای اسکالر غیراختیاری در proto3 باعث ایجاد ValueError می‌شود.)

روش‌های پیام Protobuf

میانای پیام protobuf شامل برخی روش‌های راحتی است که بخشی از میانای proto-plus نیستند؛ بااین‌حال، می‌توانید با تبدیل پیام proto-plus به همتای protobuf آن، به آن‌ها دسترسی پیدا کنید:

# Accessing the ListFields method
protobuf_campaign = util.convert_proto_plus_to_protobuf(campaign)
print(protobuf_campaign.ListFields())

# Accessing the Clear method
protobuf_campaign = util.convert_proto_plus_to_protobuf(campaign)
protobuf_campaign.Clear()

پیگیری‌کننده نسخه

اگر درباره این تغییرات سؤالی دارید یا در انتقال به جدیدترین نسخه کتابخانه با مشکلی مواجه شده‌اید، مشکل را در سیستم ردیابی مشکل ثبت کنید.