رسائل Protobuf

يقدّم الإصدار 14.0.0 من مكتبة برامج Python معلّمة ضبط جديدة مطلوبة تُسمى use_proto_plus تحدّد ما إذا كنت تريد أن تعرض المكتبة رسائل Pro-plus أو protobuf messages. للحصول على تفاصيل حول كيفية تعيين هذه المعلمة، اطلع على مستندات التهيئة.

يصف هذا القسم الآثار المترتبة على الأداء عند اختيار أنواع الرسائل التي يتم استخدامها، لذلك نوصي بقراءة الخيارات وفهمها لاتخاذ قرار مدروس. ولكن إذا أردت الترقية إلى الإصدار 14.0.0 بدون إجراء تغييرات على الرمز، يمكنك ضبط use_proto_plus على True لتجنّب إيقاف التغييرات في الواجهة.

رسائل Protoplus مقابل نماذج Protobuf

في الإصدار 10.0.0، تم نقل مكتبة برامج Python إلى أداة إنشاء رموز جديدة تم دمجها مع proto-plus كطريقة لتحسين بيئة بيئة واجهة الرسالة الأولية من خلال جعلها تبدو وكأنها كائنات Python أصلية. وتتمثّل المفاضلة بين هذا التحسّن في أنّ النموذج الأوليّ يقدّم مصاريف الأداء بشكلٍ عام

أداء Proto-plus

إحدى الفوائد الأساسية من Proto-plus هي أنه يحوّل رسائل Protobuf والأنواع المعروفة إلى أنواع Python الأصلية من خلال عملية تسمى type marsling.

يحدث التنظيم عند الوصول إلى حقل في النسخة الأولية من الرسالة الأولية، خاصة عند قراءة حقل أو تعيينه، على سبيل المثال، في تعريف نموذج أولي:

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 بحيث تتوافق القيمة مع وقت تشغيل البروتوكول.

في التحليل الذي أجريناه منذ إصدار الإصدار 10.0.0، حدَّدنا أن الوقت المستغرق في إجراء هذه النوعية من الإحالات الناجحة له تأثير كبير في الأداء لدرجة أنه من المهم منح المستخدمين خيار استخدام رسائل البروتوكول.

حالات الاستخدام لرسائل Proto-plus وProtobuf

حالات استخدام رسائل Proto-plus
تقدم Proto-plus عددًا من التحسينات المريحة على رسائل Protobuf، لذا فهي تعد مثالية لكتابة شفرة قابلة للصيانة ويمكن قراءتها. وبما أنها تعرض كائنات Python الأصلية، فإنها أسهل في الاستخدام والفهم.
حالات استخدام رسائل 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".

تسلسل وحدات البايت

رسائل 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)

عمليات التعداد

تعدد الإحصاءات التي يتم عرضها من خلال رسائل النماذج الأولية أمثلة من نوع Python الأصلي enum ولذلك تكتسب عددًا من طرق الملاءمة.

استرداد نوع الرقم 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
# To read the value of campaign status
print(status_enum.CampaignStatus.Value(campaign.status))

استرجاع اسم التعداد

من المفيد أحيانًا معرفة اسم حقل تعداد. على سبيل المثال، عند قراءة عناصر من واجهة برمجة التطبيقات، قد تحتاج إلى معرفة حالة الحملة التي يتوافق معها الرمز 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)
رسائل 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)

الحقول المتكرّرة

كما هو مبين في مستندات 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 simply check the message for
# truthiness.
is_empty = bool(campaign)
is_empty = not campaign
رسائل Protobuf
is_empty = campaign.ByteSize() == 0

نسخة الرسالة

بالنسبة إلى كل من الرسائل الأولية بالإضافة إلى الرسائل الأولية، نقترح استخدام طريقة مساعد copy_from على GoogleAdsClient:

client.copy_from(campaign, other_campaign)

حقول الرسائل فارغة

عملية إعداد حقول الرسائل الفارغة هي نفسها بغض النظر عن نوع الرسالة التي تستخدمها. ما عليك سوى نسخ رسالة فارغة في الحقل المعني. راجع قسم نسخة الرسالة إلى جانب دليل حقول الرسالة الفارغة. في ما يلي مثال على كيفية تعيين حقل رسالة فارغ:

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

أسماء الحقول التي تكون كلمات محجوزة

عند استخدام الرسائل الأولية بالإضافة إلى ذلك، تظهر أسماء الحقول تلقائيًا مع شرطة سفلية لاحقة إذا كان الاسم هو كلمة محجوزة في Python. في ما يلي مثال على التعامل مع مثيل Asset:

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

ويتم إنشاء القائمة الكاملة للأسماء المحجوزة في وحدة منشئ الرسومات. ويمكن الوصول إليه بشكل آلي أيضًا.

أولاً، ثبِّت الوحدة:

python -m pip install gapic-generator

بعد ذلك، في Python REPL أو في نص برمجي:

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

الحضور الميداني

نظرًا لأن الحقول الموجودة في مثيلات الرسائل الأولية لها قيم افتراضية، فليس من السهل دائمًا معرفة ما إذا تم تعيين الحقل أم لا.

رسائل 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")

تتضمّن واجهة الفئة البروتوكول الأولي Message طريقة HasField التي تحدِّد ما إذا كان قد تم ضبط الحقل في الرسالة، حتى في حال ضبطها على قيمة تلقائية.

طرق رسائل Protobuf

تتضمن واجهة رسالة Protobuf بعض الطرق المناسبة التي لا تعد جزءًا من واجهة 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 من المكتبة، يمكنك إرسال مشكلة على أداة التتبّع.