ข้อความ Protobuf

พารามิเตอร์การกําหนดค่า 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

จากการวิเคราะห์ประสิทธิภาพ เราพบว่าเวลาที่ใช้ทำ Conversion ประเภทเหล่านี้ส่งผลต่อประสิทธิภาพมากพอที่ผู้ใช้ควรตัดสินใจว่าจะเลือกใช้ข้อความ protobuf หรือไม่ โดยอิงตามความต้องการ

กรณีการใช้งานสำหรับข้อความ proto-plus และ protobuf

กรณีการใช้งานข้อความ Proto-Plus
Proto-plus มีการปรับปรุงหลายอย่างเพื่อให้ใช้งานได้ง่ายกว่าข้อความ protobuf จึงเหมาะสําหรับการเขียนโค้ดที่อ่านง่ายและดูแลรักษาได้ เนื่องจากแสดงออบเจ็กต์ Python ดั้งเดิม จึงใช้งานและเข้าใจได้ง่ายขึ้น
กรณีการใช้งานข้อความ Protobuf
ใช้ Protobuf สำหรับกรณีการใช้งานที่อ่อนไหวต่อประสิทธิภาพ โดยเฉพาะในแอปที่ต้องประมวลผลรายงานขนาดใหญ่อย่างรวดเร็ว หรือสร้างคำขอที่เปลี่ยนแปลงด้วยการดำเนินการจำนวนมาก เช่น ด้วย BatchJobService หรือ OfflineUserDataJobService

ประเภทข้อความที่เปลี่ยนแปลงแบบไดนามิก

หลังจากเลือกประเภทข้อความที่เหมาะสมสําหรับแอปแล้ว คุณอาจพบว่าต้องใช้ประเภทอื่นสําหรับเวิร์กโฟลว์ที่เฉพาะเจาะจง ในกรณีนี้ คุณสลับระหว่าง 2 ประเภทแบบไดนามิกได้ง่ายๆ โดยใช้ยูทิลิตีที่ไลบรารีไคลเอ็นต์มีให้ การใช้คลาสข้อความ 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)
ข้อความ 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

Enums ที่แสดงโดยข้อความ 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

ในการดึงข้อมูล Enum ให้ง่ายขึ้น อินสแตนซ์ 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
# 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)
ข้อความ 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 docs โดยทั่วไปแล้ว ช่องที่ซ้ำกันจะเทียบเท่ากับลิสต์ที่มีประเภท ซึ่งหมายความว่าช่องเหล่านี้จะทํางานเกือบเหมือนกับ 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

ข้อความ

สําหรับทั้งข้อความ 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

จากนั้นใน REPL หรือสคริปต์ Python ให้ทำดังนี้

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 ที่จะระบุว่ามีการตั้งค่าฟิลด์ในข้อความหรือไม่ แม้ว่าจะมีการตั้งค่าเป็นค่าเริ่มต้นก็ตาม

วิธีการของข้อความ 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())

เครื่องมือติดตามปัญหา

หากมีข้อสงสัยเกี่ยวกับการเปลี่ยนแปลงเหล่านี้หรือปัญหาในการย้ายข้อมูลไปยังไลบรารีเวอร์ชันล่าสุด โปรดแจ้งปัญหาในเครื่องมือติดตามของเรา