پیام های پروتوباف

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

این بخش پیامدهای عملکرد انتخاب انواع پیام‌ها را توضیح می‌دهد، بنابراین، توصیه می‌کنیم برای تصمیم‌گیری آگاهانه، گزینه‌ها را بخوانید و درک کنید. با این حال، اگر می‌خواهید بدون تغییر کد به نسخه 14.0.0 ارتقا دهید، می‌توانید use_proto_plus روی True تنظیم کنید تا از شکستن تغییرات رابط جلوگیری کنید.

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

در نسخه 10.0.0 کتابخانه کلاینت پایتون به یک خط لوله تولید کننده کد جدید منتقل شد که proto-plus را به عنوان راهی برای بهبود ارگونومی رابط پیام پروتوباف از طریق رفتار بیشتر شبیه به اشیاء بومی پایتون ادغام کرد. معاوضه این بهبود این است که proto-plus سربار عملکرد را معرفی می کند.

عملکرد پروتو پلاس

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

مارشال زمانی اتفاق می‌افتد که به یک فیلد در یک نمونه پیام 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 آن دسترسی پیدا کنید:

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

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

در تجزیه و تحلیلی که از زمان انتشار نسخه 10.0.0 انجام داده‌ایم، مشخص کرده‌ایم که زمان صرف شده برای انجام این نوع تبدیل‌ها به اندازه کافی تأثیر عملکردی دارد که مهم است به کاربران این امکان را بدهیم که از پیام‌های پروتوباف استفاده کنند.

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

موارد استفاده از پیام Proto-plus
Proto-plus تعدادی بهبود ارگونومیک را نسبت به پیام های protobuf ارائه می دهد، بنابراین برای نوشتن کد قابل نگهداری و خواندنی ایده آل هستند. از آنجایی که آنها اشیاء بومی پایتون را در معرض دید قرار می دهند، استفاده و درک آنها آسان تر است.
موارد استفاده از پیام Protobuf
از پروتوباف‌ها برای موارد استفاده حساس به عملکرد استفاده کنید، به‌ویژه در برنامه‌هایی که نیاز به پردازش سریع گزارش‌های بزرگ دارند، یا درخواست‌های جهش‌یافته را با تعداد زیادی عملیات ایجاد می‌کنند، برای مثال با 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)
پیام های پروتوباف
serialized = campaign.SerializeToString()
deserialized = campaign.FromString(serialized)

سریال سازی JSON

پیام های Proto-plus
serialized = type(campaign).to_json(campaign)
deserialized = type(campaign).from_json(serialized)
پیام های پروتوباف
from google.protobuf.json_format import MessageToJson, Parse

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

ماسک های میدانی

روش کمکی ماسک میدان ارائه شده توسط api-core برای استفاده از نمونه های پیام پروتوباف طراحی شده است. بنابراین هنگام استفاده از پیام های 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)
پیام های پروتوباف
from google.api_core.protobuf_helpers import field_mask

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

Enums

Enum هایی که توسط پیام های proto-plus در معرض نمایش قرار می گیرند، نمونه هایی از نوع enum بومی پایتون هستند و بنابراین تعدادی از روش های راحت را به ارث می برند.

بازیابی نوع Enum

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

پیام های Proto-plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
پیام های پروتوباف
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)
پیام های پروتوباف
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))

بازیابی نام Enum

گاهی اوقات دانستن نام یک فیلد enum مفید است. به عنوان مثال، هنگام خواندن اشیاء از API ممکن است بخواهید بدانید که int 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)
پیام های پروتوباف
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)

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

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

الحاق به فیلدهای اسکالر مکرر

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

پیام های Proto-plus
ad.final_urls.append("https://www.example.com")
پیام های پروتوباف
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"])
پیام های پروتوباف
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)
پیام های پروتوباف
# 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 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 simply check the message for
# truthiness.
is_empty = bool(campaign)
is_empty = not campaign
پیام های پروتوباف
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، اگر نام یک کلمه رزرو شده در پایتون باشد، نام فیلدها به‌طور خودکار با زیرخط آخر ظاهر می‌شوند. در اینجا نمونه ای از کار با یک نمونه Asset آورده شده است:

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

لیست کامل اسامی رزرو شده در ماژول مولد gapic ساخته شده است. به صورت برنامه نویسی نیز قابل دسترسی است.

ابتدا ماژول را نصب کنید:

python -m pip install gapic-generator

سپس، در یک REPL یا اسکریپت پایتون:

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

حضور میدانی

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

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

رابط کلاس Message protobuf دارای یک روش HasField است که تعیین می کند آیا فیلد روی پیام تنظیم شده است، حتی اگر روی یک مقدار پیش فرض تنظیم شده باشد.

روش های پیام پروتوباف

رابط پیام protobuf شامل برخی از روش‌های راحتی است که بخشی از رابط proto-plus نیستند. با این حال، دسترسی به آنها با تبدیل یک پیام proto-plus به همتای 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())

ردیاب مشکل

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