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