באמצעות פרמטר ההגדרה use_proto_plus, אפשר לציין אם רוצים שהספרייה תחזיר הודעות proto-plus או הודעות protobuf. פרטים על הגדרת הפרמטר הזה זמינים במסמכי ההגדרה.
בקטע הזה נתאר את ההשלכות של כל אפשרות על הביצועים, כדי שתוכלו לבחור את הגישה הכי טובה לאפליקציה שלכם.
ההבדלים בין Proto-plus לבין הודעות protobuf
צינור יצירת הקוד משלב את 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.
הזמן שנדרש לביצוע המרות מסוגים כאלה משפיע באופן משמעותי על הביצועים, ולכן כדאי להחליט, על סמך הצרכים של האפליקציה, אם להשתמש בהודעות proto-plus או protobuf.
תרחישי שימוש בהודעות proto-plus ו-protobuf
- תרחישי שימוש בהודעות Proto-plus
- Proto-plus מציע מספר שיפורים ארגונומיים בהשוואה להודעות protobuf, ולכן הוא אידיאלי לכתיבת קוד שקל לתחזק ולקרוא. הם חושפים אובייקטים סטנדרטיים של Python, ולכן קל יותר להשתמש בהם ולהבין אותם.
- תרחישים לדוגמה לשימוש בהודעות Protobuf
- מומלץ להשתמש ב-protobufs בתרחישי שימוש שבהם הביצועים חשובים, במיוחד באפליקציות שצריכות לעבד במהירות דוחות גדולים, או באפליקציות שיוצרות בקשות לשינוי עם מספר גדול של פעולות, למשל עם
BatchJobServiceאו עםOfflineUserDataJobService.
שינוי דינמי של סוגי ההודעות
אחרי שתבחרו את סוג ההודעה המתאים לאפליקציה, יכול להיות שתצטרכו להשתמש בסוג השני עבור תהליך עבודה ספציפי. במקרה כזה, אפשר לעבור בין שני הסוגים באופן דינמי באמצעות כלי עזר שמוצעים בספריית הלקוח. באמצעות אותו Dog message class מהשלב הקודם:
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)
טיפוסים בני מנייה (enum)
ערכי enum שנחשפים על ידי הודעות proto-plus הם מופעים של הסוג המובנה enum של Python, ולכן הם יורשים מספר שיטות נוחות.
אחזור של סוגים בני מנייה (enum)
כשמשתמשים בשיטה GoogleAdsClient.get_type כדי לאחזר enum, ההודעות שמוחזרות שונות מעט בהתאם לסוג ההודעות שבהן משתמשים – 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
אחזור ערך 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)
- הודעות 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"))
אחזור שם של טיפוס בן מנייה (enum)
לפעמים כדאי לדעת את השם של שדה enum. לדוגמה, כשקוראים אובייקטים מה-API, יכול להיות שתרצו לדעת לאיזה סטטוס קמפיין מתאים המספר השלם 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 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
- הודעות 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()
מעקב אחר בעיות
אם יש לכם שאלות לגבי השינויים האלה או בעיות במעבר לגרסה העדכנית של הספרייה, אתם יכולים לדווח על בעיה ב-Issue Tracker.