use_proto_plus
構成パラメータを使用すると、ライブラリが proto-plus メッセージと protobuf メッセージのどちらを返すかを指定できます。このパラメータの設定方法について詳しくは、構成ドキュメントをご覧ください。
このセクションでは、使用するメッセージのタイプを選択することによるパフォーマンスへの影響について説明します。そのため、十分な情報に基づいて決定できるように、オプションを読んで理解することをおすすめします。
proto-plus と protobuf メッセージ
コード生成パイプラインは、protobuf メッセージ インターフェースの人間工学を改善するために、proto-plus を統合して、ネイティブ Python オブジェクトのように動作するようにします。ただし、proto-plus を使用すると、パフォーマンスのオーバーヘッドが発生します。
Proto-plus のパフォーマンス
proto-plus の主なメリットの 1 つは、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
クラスを初期化し、他の Python オブジェクトと同様に name
フィールドにアクセスできます。
dog = Dog()
dog.name = "Scruffy"
print(dog.name)
name
フィールドの読み取りと設定を行うと、値がネイティブの Python str
型から string
型に変換され、protobuf ランタイムとの互換性が確保されます。
パフォーマンス分析の結果、この型の変換にかかる時間はパフォーマンスに大きな影響を与えるため、protobuf メッセージを使用するかどうかは、ユーザーがニーズに基づいて判断する必要があることがわかりました。
proto-plus メッセージと protobuf メッセージのユースケース
- Proto-plus メッセージのユースケース
- Proto-plus は protobuf メッセージよりも人間工学的に優れているため、保守しやすく読みやすいコードの作成に最適です。ネイティブ Python オブジェクトを公開するため、使いやすく理解しやすくなっています。
- Protobuf メッセージのユースケース
- パフォーマンスが重要なユースケース、特に大量のレポートを迅速に処理する必要があるアプリや、
BatchJobService
やOfflineUserDataJobService
など、多数のオペレーションを含む変更リクエストを構築するアプリでは、protobuf を使用します。
メッセージ タイプを動的に変更する
アプリに適したメッセージ タイプを選択した後、特定のワークフローで別のタイプを使用する必要があることがわかる場合があります。この場合、クライアント ライブラリが提供するユーティリティを使用して、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)
列挙型
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 からオブジェクトを読み取るときに、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 ドキュメントで説明されているように、繰り返しフィールドは通常、型付きリストと同等です。つまり、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)
空のメッセージ フィールド
空のメッセージ フィールドを設定するプロセスは、使用しているメッセージ タイプに関係なく同じです。問題のフィールドに空のメッセージをコピーするだけです。メッセージのコピーのセクションと、メッセージ フィールドが空の場合のガイドも参照してください。空のメッセージ フィールドを設定する方法の例を次に示します。
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
メソッドがあります。
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())
公開バグトラッカー
これらの変更についてご不明な点がある場合や、ライブラリの最新バージョンへの移行で問題が発生した場合は、トラッカーで問題を報告してください。