Thông báo Protobuf

Với tham số cấu hình use_proto_plus, bạn có thể chỉ định xem bạn muốn thư viện trả về thông báo proto-plus hay thông báo protobuf. Để biết thông tin chi tiết về cách đặt tham số này, hãy xem tài liệu về cấu hình.

Phần này mô tả mức độ ảnh hưởng đến hiệu suất của từng lựa chọn để bạn có thể chọn phương pháp phù hợp nhất cho ứng dụng của mình.

Thông báo proto-plus so với protobuf

Quy trình tạo mã tích hợp proto-plus để cải thiện tính tiện dụng của giao diện thông báo protobuf bằng cách làm cho chúng hoạt động giống như các đối tượng Python tiêu chuẩn hơn. Tuy nhiên, điều này có nghĩa là việc sử dụng proto-plus sẽ làm tăng mức hao tổn hiệu suất.

Hiệu suất của Proto-plus

Một trong những lợi ích cốt lõi của proto-plus là chuyển đổi thông báo protobuf và các loại phổ biến thành các loại Python tích hợp sẵn thông qua một quy trình gọi là sắp xếp loại.

Quá trình sắp xếp xảy ra khi một trường được truy cập trên một thực thể thông báo proto-plus, cụ thể là khi một trường được đọc hoặc đặt, ví dụ: trong định nghĩa protobuf:

syntax = "proto3";

message Dog {
  string name = 1;
}

Khi định nghĩa này được chuyển đổi thành một lớp proto-plus, định nghĩa này sẽ có dạng như sau:

import proto


class Dog(proto.Message):
    name = proto.Field(proto.STRING, number=1)

Sau đó, bạn có thể khởi động lớp Dog và truy cập vào trường name của lớp đó như mọi đối tượng Python khác:

dog = Dog()
dog.name = "Scruffy"
print(dog.name)

Khi đọc và đặt trường name, giá trị sẽ được chuyển đổi từ loại str tích hợp sẵn của Python sang loại string để giá trị đó tương thích với thời gian chạy protobuf.

Thời gian thực hiện các lượt chuyển đổi loại này có tác động đủ lớn đến hiệu suất để bạn quyết định (dựa trên nhu cầu của ứng dụng) xem nên sử dụng thông báo proto-plus hay protobuf.

Trường hợp sử dụng thông báo proto-plus và protobuf

Trường hợp sử dụng thông báo proto-plus
Proto-plus cung cấp một số điểm cải tiến về tính tiện dụng so với thông báo protobuf, nên rất phù hợp để viết mã dễ đọc và dễ bảo trì. Vì hiển thị các đối tượng Python chuẩn nên các đối tượng này dễ sử dụng và dễ hiểu hơn.
Trường hợp sử dụng thông báo Protobuf
Sử dụng protobuf cho các trường hợp sử dụng cần chú trọng hiệu suất, đặc biệt là trong các ứng dụng cần xử lý nhanh báo cáo lớn hoặc tạo yêu cầu thay đổi tài nguyên có số lượng lớn thao tác, chẳng hạn như với BatchJobService hoặc OfflineUserDataJobService.

Chuyển đổi loại thông báo một cách linh động

Sau khi chọn loại thông báo phù hợp cho ứng dụng, bạn có thể thấy rằng mình cần sử dụng loại thông báo khác cho một quy trình công việc cụ thể. Trong trường hợp này, bạn có thể chuyển đổi linh động giữa hai loại bằng cách sử dụng các tiện ích do thư viện ứng dụng cung cấp. Sử dụng cùng một lớp thông báo Dog từ trước đó:

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)

Sự khác biệt về giao diện thông báo Protobuf

Giao diện proto-plus được ghi lại chi tiết và các phần sau đây nêu bật những điểm khác biệt chính ảnh hưởng đến các trường hợp sử dụng phổ biến cho thư viện ứng dụng Google Ads.

Chuyển đổi tuần tự byte

Thông báo Proto-plus
serialized = type(campaign).serialize(campaign)
deserialized = type(campaign).deserialize(serialized)
Thông báo Protobuf
serialized = campaign.SerializeToString()
deserialized = campaign.FromString(serialized)

Chuyển đổi tuần tự JSON

Thông báo Proto-plus
serialized = type(campaign).to_json(campaign)
deserialized = type(campaign).from_json(serialized)
Thông báo Protobuf
from google.protobuf.json_format import MessageToJson, Parse

serialized = MessageToJson(campaign)
deserialized = Parse(serialized, campaign)

Mặt nạ trường

Phương thức trợ giúp mặt nạ trường do api-core cung cấp được thiết kế để sử dụng các thực thể thông báo protobuf. Khi sử dụng thông báo proto-plus, hãy chuyển đổi chúng thành thông báo protobuf để sử dụng trình trợ giúp:

Thông báo 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)
Thông báo Protobuf
from google.api_core.protobuf_helpers import field_mask

campaign = client.get_type("Campaign")
mask = field_mask(None, campaign)

Enum

Enum do thông báo proto-plus hiển thị là các thực thể của loại enum tích hợp sẵn của Python, do đó kế thừa một số phương thức tiện lợi.

Truy xuất loại enum

Khi sử dụng phương thức GoogleAdsClient.get_type để truy xuất enum, các thông báo được trả về sẽ hơi khác nhau tuỳ thuộc vào việc bạn đang sử dụng thông báo proto-plus hay protobuf. Ví dụ:

Thông báo Proto-plus
val = client.get_type("CampaignStatusEnum").CampaignStatus.PAUSED
Thông báo Protobuf
val = client.get_type("CampaignStatusEnum").PAUSED

Để đơn giản hoá việc truy xuất enum, có một thuộc tính tiện lợi trên các thực thể GoogleAdsClient có giao diện nhất quán bất kể bạn đang sử dụng loại thông báo nào:

val = client.enums.CampaignStatusEnum.PAUSED

Truy xuất giá trị enum

Đôi khi, bạn nên biết giá trị hoặc mã nhận dạng trường của một enum nhất định, ví dụ: PAUSED trên CampaignStatusEnum tương ứng với 3:

Thông báo Proto-plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the value of campaign status
print(campaign.status.value)
Thông báo 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"))

Truy xuất tên enum

Đôi khi, bạn nên biết tên của một trường enum. Ví dụ: khi đọc các đối tượng từ API, bạn có thể muốn biết trạng thái chiến dịch nào tương ứng với số nguyên 3:

Thông báo Proto-plus
campaign = client.get_type("Campaign")
campaign.status = client.enums.CampaignStatusEnum.PAUSED
# To read the name of campaign status
print(campaign.status.name)
Thông báo 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))

Các trường lặp lại

Như được mô tả trong tài liệu về proto-plus, các trường lặp lại thường tương đương với danh sách đã nhập, tức là chúng hoạt động gần giống với list.

Thêm giá trị vào các trường vô hướng lặp lại

Khi thêm giá trị vào các trường loại vô hướng lặp lại, ví dụ: trường string hoặc int64, giao diện sẽ giống nhau bất kể loại thông báo:

Thông báo Proto-plus
ad.final_urls.append("https://www.example.com")
Thông báo Protobuf
ad.final_urls.append("https://www.example.com")

Điều này cũng bao gồm tất cả các phương thức list phổ biến khác, ví dụ: extend:

Thông báo Proto-plus
ad.final_urls.extend(
    ["https://www.example.com", "https://www.example.com/2"]
)
Thông báo Protobuf
ad.final_urls.extend(
    ["https://www.example.com", "https://www.example.com/2"]
)

Thêm các loại thông báo vào các trường lặp lại

Nếu trường lặp lại không phải là kiểu vô hướng, thì hành vi khi thêm các trường đó vào trường lặp lại sẽ hơi khác:

Thông báo Proto-plus
frequency_cap = client.get_type("FrequencyCapEntry")
frequency_cap.cap = 100
campaign.frequency_caps.append(frequency_cap)
Thông báo Protobuf
# The add method initializes a message and adds it to the repeated field
frequency_cap = campaign.frequency_caps.add()
frequency_cap.cap = 100

Chỉ định các trường lặp lại

Đối với cả trường lặp lại vô hướng và không vô hướng, bạn có thể chỉ định danh sách cho trường theo nhiều cách:

Thông báo Proto-plus
# In proto-plus it's possible to use assignment.
urls = ["https://www.example.com"]
ad.final_urls = urls
Thông báo 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

Tin nhắn trống

Đôi khi, bạn nên biết liệu một thực thể thông báo có chứa thông tin nào hay không hoặc có trường nào được đặt hay không.

Thông báo Proto-plus
# When using proto-plus messages you can check the message for truthiness.
is_empty = not bool(campaign)
Thông báo Protobuf
is_empty = campaign.ByteSize() == 0

Bản sao tin nhắn

Đối với cả thông báo proto-plus và protobuf, hãy sử dụng phương thức trợ giúp copy_from trên GoogleAdsClient:

client.copy_from(campaign, other_campaign)

Trường thông báo trống

Quy trình đặt các trường thông báo trống là như nhau, bất kể loại thông báo bạn đang sử dụng. Bạn sao chép một thông báo trống vào trường được đề cập. Hãy xem phần Nội dung thông báo cũng như hướng dẫn về Trường thông báo trống. Ví dụ sau đây cho thấy cách đặt trường thông báo trống:

client.copy_from(campaign.manual_cpm, client.get_type("ManualCpm"))

Tên trường là từ dành riêng

Khi sử dụng thông báo proto-plus, tên trường sẽ tự động xuất hiện kèm theo dấu gạch dưới ở cuối nếu tên đó cũng là một từ dành riêng trong Python. Ví dụ sau đây cho thấy cách làm việc với một thực thể Asset:

asset = client.get_type("Asset")
asset.type_ = client.enums.AssetTypeEnum.IMAGE

Danh sách đầy đủ các tên dành riêng được tạo trong mô-đun gapic generator. Bạn cũng có thể truy cập vào trang này theo phương thức lập trình.

Trước tiên, hãy cài đặt mô-đun:

python -m pip install gapic-generator

Sau đó, trong REPL hoặc tập lệnh Python:

import gapic.utils

print(gapic.utils.reserved_names.RESERVED_NAMES)

Sự hiện diện của trường

Vì các trường trên thực thể thông báo protobuf có giá trị mặc định, nên không phải lúc nào bạn cũng dễ dàng biết được một trường đã được đặt hay chưa.

Thông báo Proto-plus
# Use the "in" operator.
has_field = "name" in campaign
Thông báo Protobuf
campaign = client.get_type("Campaign")
# Determines whether "name" is set and not just an empty string.
campaign.HasField("name")

Giao diện lớp Message của protobuf có một phương thức HasField xác định xem một thông báo phụ, trường oneof hoặc trường vô hướng optional trên một thông báo đã được đặt hay chưa, ngay cả khi thông báo đó được đặt thành giá trị mặc định. (Việc gọi HasField trên các trường vô hướng không bắt buộc trong proto3 sẽ tạo ra ValueError.)

Phương thức thông báo Protobuf

Giao diện thông báo protobuf bao gồm một số phương thức tiện lợi không thuộc giao diện proto-plus; tuy nhiên, bạn có thể truy cập vào các phương thức đó bằng cách chuyển đổi thông báo proto-plus thành thông báo protobuf tương ứng:

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

Trình theo dõi sự cố

Nếu bạn có thắc mắc về những thay đổi này hoặc gặp vấn đề khi di chuyển sang phiên bản mới nhất của thư viện, hãy gửi sự cố trên trình theo dõi sự cố.