您可以使用 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 欄位時,值會從內建的 Python str 型別轉換為 string 型別,確保值與 protobuf 執行階段相容。
執行這類轉換所花費的時間對效能影響很大,因此您應根據應用程式需求,決定是否使用 proto-plus 或 protobuf 訊息。
proto-plus 和 protobuf 訊息的用途
- Proto-plus 訊息用途
- Proto-plus 在人體工學方面比 protobuf 訊息有許多改良之處,因此非常適合用來編寫可維護的易讀程式碼。由於這些物件會公開標準 Python 物件,因此更容易使用和瞭解。
- Protobuf 訊息用途
- 針對注重效能的使用情境使用 protobuf,特別是在需要快速處理大型報表,或使用大量作業建構變動要求的應用程式中,例如
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 訊息介面差異
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)
列舉
proto-plus 訊息公開的列舉是 Python 內建 enum 型別的執行個體,因此會繼承許多便利方法。
擷取列舉型別
使用 GoogleAdsClient.get_type 方法擷取列舉時,傳回的訊息會略有不同,視您使用的是 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
擷取列舉值
有時瞭解特定列舉的 ID 值或欄位 ID 很有用,例如 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"))
擷取列舉名稱
有時瞭解列舉欄位的名稱很有用。舉例來說,從 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 訊息,請在 GoogleAdsClient 上使用 copy_from 輔助方法:
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 純量欄位是否已設定,即使是設為預設值也算。(在 proto3 中對非選用純量欄位呼叫 HasField 會引發 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 上回報問題。