رسائل Protobuf

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

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

رسائل Proto-plus مقابل رسائل Protobuf

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

أداء Proto-plus

تتمثل إحدى الفوائد الأساسية لـ proto-plus في أنه يحوّل رسائل protobuf والأنواع المعروفة إلى أنواع أصلية في Python من خلال عملية تسمى 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 الخاص بها كما تفعل مع أي كائن Python آخر:

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

عند قراءة الحقل name وإعداده، يتم تحويل القيمة من النوع str الأصلي في Python إلى النوع string لكي تتوافق القيمة مع وقت تشغيل protobuf.

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

حالات الاستخدام لرسائل Protoplus وProtobuf

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

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

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

نسخة الرسالة

بالنسبة إلى كل من رسائل Protoplus و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)

التواجد في الحقل

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

رسائل 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، ومع ذلك، يسهل الوصول إليها عن طريق تحويل رسالة 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 من المكتبة، يمكنك الإبلاغ عن مشكلة على جهاز التتبُّع.