प्रोटोबफ़ मैसेज

use_proto_plus कॉन्फ़िगरेशन पैरामीटर की मदद से, यह तय किया जा सकता है कि आपको लाइब्रेरी से proto-plus मैसेज चाहिए या protobuf मैसेज. इस पैरामीटर को सेट करने के तरीके के बारे में जानने के लिए, कॉन्फ़िगरेशन दस्तावेज़ देखें.

इस सेक्शन में, हर विकल्प की परफ़ॉर्मेंस के बारे में बताया गया है, ताकि आप अपने ऐप्लिकेशन के लिए सबसे सही तरीका चुन सकें.

Proto-plus बनाम protobuf मैसेज

कोड जनरेटर पाइपलाइन, proto-plus को इंटिग्रेट करती है. इससे protobuf मैसेज इंटरफ़ेस को बेहतर बनाया जा सकता है. इसके लिए, उन्हें स्टैंडर्ड Python ऑब्जेक्ट की तरह काम करने के लिए बनाया जाता है. हालांकि, इसका मतलब है कि proto-plus का इस्तेमाल करने से, परफ़ॉर्मेंस ओवरहेड की समस्या आती है.

Proto-plus की परफ़ॉर्मेंस

Proto-plus का एक मुख्य फ़ायदा यह है कि यह टाइप मार्शलिंग नाम की प्रोसेस के ज़रिए, protobuf मैसेज और जाने-माने टाइप को पहले से मौजूद Python टाइप में बदल देता है.

मार्शलिंग तब होती है, जब प्रोटो-प्लस मैसेज इंस्टेंस पर किसी फ़ील्ड को ऐक्सेस किया जाता है. खास तौर पर, जब किसी फ़ील्ड को पढ़ा या सेट किया जाता है. उदाहरण के लिए, 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 मैसेज इंटरफ़ेस में अंतर

प्रोटो-प्लस इंटरफ़ेस के बारे में ज़्यादा जानकारी दी गई है. साथ ही, यहां दिए गए सेक्शन में उन मुख्य अंतरों के बारे में बताया गया है जो 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 से मिलने वाले फ़ील्ड मास्क हेल्पर तरीके को 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)
प्रोटोबफ़ मैसेज
from google.api_core.protobuf_helpers import field_mask

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

Enums

Proto-plus मैसेज से एक्सपोज़ किए गए enum, Python के पहले से मौजूद enum टाइप के इंस्टेंस होते हैं. इसलिए, इनमें कई सुविधाजनक तरीके पहले से मौजूद होते हैं.

Enum टाइप की जानकारी पाना

enum को वापस पाने के लिए GoogleAdsClient.get_type तरीके का इस्तेमाल करने पर, जो मैसेज दिखाए जाते हैं वे इस बात पर निर्भर करते हैं कि proto-plus या protobuf मैसेज का इस्तेमाल किया जा रहा है या नहीं. उदाहरण के लिए:

Proto-plus मैसेज
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
प्रोटोबफ़ मैसेज
val = client.get_type("CampaignStatusEnum").PAUSED

enum को आसानी से वापस पाने के लिए, GoogleAdsClient इंस्टेंस पर एक सुविधाजनक एट्रिब्यूट मौजूद होता है. इसमें एक जैसा इंटरफ़ेस होता है. इससे कोई फ़र्क़ नहीं पड़ता कि किस तरह के मैसेज का इस्तेमाल किया जा रहा है:

val = client.enums.CampaignStatusEnum.PAUSED

Enum वैल्यू को वापस पाना

कभी-कभी किसी enum की वैल्यू या फ़ील्ड आईडी जानना काम का होता है. उदाहरण के लिए, CampaignStatusEnum पर PAUSED, 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
# 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 का नाम वापस पाना

कभी-कभी, 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)
प्रोटोबफ़ मैसेज
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")
प्रोटोबफ़ मैसेज
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 check the message for truthiness.
is_empty = not bool(campaign)
प्रोटोबफ़ मैसेज
is_empty = campaign.ByteSize() == 0

मैसेज कॉपी

Proto-plus और protobuf, दोनों मैसेज के लिए, GoogleAdsClient पर copy_from हेल्पर तरीके का इस्तेमाल करें:

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

रिज़र्व किए गए नामों की पूरी सूची, gapic generator मॉड्यूल में बनाई जाती है. इसे प्रोग्राम के हिसाब से भी ऐक्सेस किया जा सकता है.

सबसे पहले, मॉड्यूल इंस्टॉल करें:

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
प्रोटोबफ़ मैसेज
campaign = client.get_type("Campaign")
# Determines whether "name" is set and not just an empty string.
campaign.HasField("name")

protobuf Message क्लास इंटरफ़ेस में एक HasField तरीका होता है. इससे यह तय होता है कि किसी मैसेज पर सब-मैसेज, oneof फ़ील्ड या optional स्केलर फ़ील्ड सेट किया गया है या नहीं. भले ही, उसे डिफ़ॉल्ट वैल्यू पर सेट किया गया हो. (proto3 में ज़रूरी स्केलर फ़ील्ड पर HasField को कॉल करने से, ValueError ट्रिगर होता है.)

प्रोटोबफ़ मैसेज के तरीके

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

Issue Tracker

अगर आपको इन बदलावों के बारे में कुछ पूछना है या लाइब्रेरी के नए वर्शन पर माइग्रेट करने में कोई समस्या आ रही है, तो समस्या को ट्रैक करने वाले टूल पर समस्या की शिकायत करें.