Python 用戶端程式庫的 14.0.0
版本導入名為 use_proto_plus
的新必要設定參數,該參數會指定您希望程式庫傳回 proto-plus 訊息或 protobuf 訊息。如要進一步瞭解如何設定此參數,請參閱設定說明文件。
本節說明選擇使用的訊息類型對效能的影響,因此建議您詳閱並瞭解選項,以便做出明智的決定。不過,如果想在不變更程式碼的情況下升級至 14.0.0
版本,可以將 use_proto_plus
設為 True
,以免破壞介面變更。
Proto Plus 與 protobuf 訊息
在 10.0.0
版本中,Python 用戶端程式庫遷移至新的程式碼產生器管道,整合 proto-plus 以改善 protobuf 訊息介面的人體工學,使其運作方式更接近原生 Python 物件。這項改進的取捨,是 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 執行階段相容。
自 10.0.0
版發布以來,我們執行了一項分析,判定執行這些類型轉換的時間對效能的影響相當大,因此讓使用者選擇使用 protobuf 訊息十分重要。
proto-plus 和 protobuf 訊息的用途
- Proto Plus 訊息用途
- 相較於 protobuf 訊息,Proto-Plus 提供多項符合人體工學的改善項目,因此相當適合用於編寫可維護且可讀的程式碼。由於這類物件公開了原生 Python 物件,因此更容易使用及理解。
- 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 會很有用,例如 CampaignStatusEnum
上的 PAUSED
對應至 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))
列舉名稱擷取
有時候,瞭解列舉欄位的名稱會有幫助。舉例來說,從 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 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 simply check the message for # truthiness. is_empty = bool(campaign) is_empty = not campaign
- Protobuf 訊息
is_empty = campaign.ByteSize() == 0
訊息文案
針對 proto-plus 和 protobuf 訊息,建議您在 GoogleAdsClient
上使用 copy_from
輔助方法:
client.copy_from(campaign, other_campaign)
空白郵件欄位
無論您使用的訊息類型為何,設定空白訊息欄位的程序都相同。您只需將空白訊息複製到問題欄位中即可請參閱「Message copy」一節和「Empty MessageFields」指南。以下範例說明如何設定空白訊息欄位:
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 Builder 模組中建構。您也可以透過程式輔助方式存取檔案。
首先,請安裝模組:
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
方法,可判斷訊息中的欄位是否已設定,即使設為預設值也一樣。
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())
Issue tracker
如果您對這些變更有任何疑問,或對遷移至程式庫 14.0.0
版本的任何問題,請透過我們的追蹤程式回報問題。