پیام‌های 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، مقدار از نوع str داخلی Python به نوع 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)

شمارشی‌ها

تعداد ثابت‌های نمایان‌شده توسط پیام‌های proto-plus نمونه‌هایی از نوع داخلی Python enum هستند و بنابراین تعدادی از روش‌های راحت را به‌ارث می‌برند.

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

هنگام استفاده از روش 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

واکشی مقدار شمارشی

گاهی اوقات دانستن مقدار یا شناسه فیلد یک شمارش معین مفید است، برای مثال، 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"))

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

گاهی اوقات دانستن نام فیلد شمارشی مفید است. برای مثال، هنگام خواندن اشیا از «میانای برنامه‌سازی کاربردی» ممکن است بخواهید بدانید عدد صحیح 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 ساخته می‌شود. ازطریق برنامه‌نویسی نیز می‌توان به آن دسترسی داشت.

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

python -m pip install gapic-generator

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

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

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

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