ข้อความ Protobuf

use_proto_plusพารามิเตอร์การกำหนดค่าช่วยให้คุณระบุได้ว่าต้องการให้ไลบรารีแสดงผลเป็นข้อความ proto-plus หรือข้อความ protobuf ดูรายละเอียดเกี่ยวกับวิธี ตั้งค่าพารามิเตอร์นี้ได้ที่เอกสารการกำหนดค่า

ส่วนนี้จะอธิบายผลกระทบด้านประสิทธิภาพของแต่ละตัวเลือก เพื่อให้คุณเลือกแนวทางที่ดีที่สุดสำหรับแอปพลิเคชันได้

ข้อความ Proto-plus กับข้อความ Protocol Buffer

ไปป์ไลน์เครื่องมือสร้างโค้ดจะผสานรวม proto-plus เพื่อปรับปรุงการยศาสตร์ของอินเทอร์เฟซข้อความ Protobuf โดยทำให้ทำงานเหมือนออบเจ็กต์ Python มาตรฐานมากขึ้น อย่างไรก็ตาม การใช้ proto-plus จะทำให้เกิดค่าใช้จ่ายด้านประสิทธิภาพ

ประสิทธิภาพของ Proto-plus

ข้อดีหลักอย่างหนึ่งของ Proto-Plus คือการแปลงข้อความ Protobuf และประเภทที่รู้จักกันดีเป็นประเภท Python ในตัวผ่านกระบวนการที่เรียกว่าการจัดประเภท

การจัดรูปแบบจะเกิดขึ้นเมื่อมีการเข้าถึงฟิลด์ในอินสแตนซ์ข้อความ 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 ประเภทนี้มีผลต่อประสิทธิภาพมากพอที่คุณควรตัดสินใจว่าจะใช้ข้อความ proto-plus หรือ 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
# 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 นอกจากนี้ยังเข้าถึงได้แบบเป็นโปรแกรมด้วย

ก่อนอื่นให้ติดตั้งโมดูลโดยทำดังนี้

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

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

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