我想在一个服务器请求中删除一些广告。有什么区别:
- 批处理(仅异步?)
- 批量变异(仅同步,更短的代码?)
我已经尝试了两种方法并得到了错误:
- 批量处理
我试图按照这篇关于创建异步批处理作业来删除多个广告的帖子。batch-processing
它已发送到服务器,但我没有看到发送的广告 ID 被删除。
我想念什么吗?
class ServiceWrapper:
"""Wraps GoogleAdsService API request"""
# public properties ...
def __init__(self, client, customer_id):
self._client = client
self._ga_service = client.get_service("GoogleAdsService")
self._ad_group_ad_service = client.get_service("AdGroupAdService")
self._batch_job_service = client.get_service("BatchJobService")
self._customer_id = customer_id
self._batch_job_operation = self._create_batch_job_operation(client)
self._batch_job_resource_name = self._create_batch_job(self._batch_job_service, customer_id,
self._batch_job_operation)
def _create_batch_job_operation(self, client):
"""Created a BatchJobOperation and sets an empty BatchJob instance to
the "create" property in order to tell the Google Ads API that we're
creating a new BatchJob.
Args:
client: an initialized GoogleAdsClient instance.
Returns: a BatchJobOperation with a BatchJob instance set in the "create"
property.
"""
batch_job_operation = client.get_type("BatchJobOperation")
batch_job = client.get_type("BatchJob")
client.copy_from(batch_job_operation.create, batch_job)
return batch_job_operation
def _create_batch_job(self, batch_job_service, customer_id, batch_job_operation):
"""Creates a batch job for the specified customer ID.
Args:
batch_job_service: an instance of the BatchJobService message class.
customer_id: a str of a customer ID.
batch_job_operation: a BatchJobOperation instance set to "create"
Returns: a str of a resource name for a batch job.
"""
try:
response = batch_job_service.mutate_batch_job(
customer_id=customer_id, operation=batch_job_operation
)
resource_name = response.result.resource_name
print(f'Created a batch job with resource name "{resource_name}"')
return resource_name
except GoogleAdsException as exception:
handle_googleads_exception(exception)
def add_all_batch_job_operations(self, batch_job_service, operations, resource_name):
"""Adds all mutate operations to the batch job.
As this is the first time for this batch job, we pass null as a sequence
token. The response will contain the next sequence token that we can use
to upload more operations in the future.
Args:
batch_job_service: an instance of the BatchJobService message class.
operations: a list of a mutate operations.
resource_name: a str of a resource name for a batch job.
"""
try:
response = batch_job_service.add_batch_job_operations(
resource_name=resource_name,
sequence_token=None,
mutate_operations=operations,
)
print(
f"{response.total_operations} mutate operations have been "
"added so far."
)
# You can use this next sequence token for calling
# add_batch_job_operations() next time.
print(
"Next sequence token for adding next operations is "
f"{response.next_sequence_token}"
)
except GoogleAdsException as exception:
handle_googleads_exception(exception)
def remove_disapproved_ads_for_account(account):
"""Remove all disapproved ads for a given customer id"""
ad_removal_operations = []
for row in rows:
ad_removal_operations.append(
build_removal_operation(customer_id, ad_json["ad_group_id"],
if len(ad_removal_operations) > 0:
remove_ads(ad_removal_operations)
#serviceWrapper.mutate(customer_id, [mutate_operation1, mutate_operation2])
def build_removal_operation(customer_id, ad_group_id, ad_id):
"""Removes the specified ad"""
resource_name = serviceWrapper.ad_group_ad_service.ad_group_ad_path(
customer_id, ad_group_id, ad_id
)
ad_group_ad_operation = serviceWrapper.client.get_type("AdGroupAdOperation")
ad_group_ad_operation.remove = resource_name
return ad_group_ad_operation
async def remove_ads(removal_operations):
"""Removes the specified ad"""
serviceWrapper.add_all_batch_job_operations(serviceWrapper.batch_job_service, removal_operations,
serviceWrapper.batch_job_resource_name)
operations_response = _run_batch_job(serviceWrapper.batch_job_service, serviceWrapper.batch_job_resource_name)
# Create an asyncio.Event instance to control execution during the
# asyncronous steps in _poll_batch_job. Note that this is not important
# for polling asyncronously, it simply helps with execution control so we
# can run _fetch_and_print_results after the asyncronous operations have
# completed.
_done_event = asyncio.Event()
_poll_batch_job(operations_response, _done_event)
# Execution will stop here and wait for the asyncronous steps in
# _poll_batch_job to complete before proceeding.
await _done_event.wait()
_fetch_and_print_results(serviceWrapper.client, serviceWrapper.batch_job_service,
serviceWrapper.batch_job_resource_name)
def _run_batch_job(batch_job_service, resource_name):
"""Runs the batch job for executing all uploaded mutate operations.
Args:
batch_job_service: an instance of the BatchJobService message class.
resource_name: a str of a resource name for a batch job.
Returns: a google.api_core.operation.Operation instance.
"""
try:
response = batch_job_service.run_batch_job(resource_name=resource_name)
print(
f'Batch job with resource name "{resource_name}" has been '
"executed."
)
return response
except GoogleAdsException as exception:
handle_googleads_exception(exception)
def _poll_batch_job(operations_response, event):
"""Polls the server until the batch job execution finishes.
Sets the initial poll delay time and the total time to wait before time-out.
Args:
operations_response: a google.api_core.operation.Operation instance.
event: an instance of asyncio.Event to invoke once the operations have
completed, alerting the awaiting calling code that it can proceed.
"""
loop = asyncio.get_event_loop()
def _done_callback(future):
# The operations_response object will call callbacks from a daemon
# thread so we must use a threadsafe method of setting the event here
# otherwise it will not trigger the awaiting code.
loop.call_soon_threadsafe(event.set)
# operations_response represents a Long-Running Operation or LRO. The class
# provides an interface for polling the API to check when the operation is
# complete. Below we use the asynchronous interface, but there's also a
# synchronous interface that uses the Operation.result method.
# See: https://googleapis.dev/python/google-api-core/latest/operation.html
operations_response.add_done_callback(_done_callback)
def _fetch_and_print_results(client, batch_job_service, resource_name):
"""Prints all the results from running the batch job.
Args:
client: an initialized GoogleAdsClient instance.
batch_job_service: an instance of the BatchJobService message class.
resource_name: a str of a resource name for a batch job.
"""
print(
f'Batch job with resource name "{resource_name}" has finished. '
"Now, printing its results..."
)
list_results_request = client.get_type("ListBatchJobResultsRequest")
list_results_request.resource_name = resource_name
list_results_request.page_size = BULK_REMOVE_PAGE_SIZE
# Gets all the results from running batch job and prints their information.
batch_job_results = batch_job_service.list_batch_job_results(
request=list_results_request
)
for batch_job_result in batch_job_results:
status = batch_job_result.status.message
status = status if status else "N/A"
result = batch_job_result.mutate_operation_response
result = result or "N/A"
print(
f"Batch job #{batch_job_result.operation_index} "
f'has a status "{status}" and response type "{result}"'
)
# [END add_complete_campaigns_using_batch_job_4]
- 批量突变
如果我选择关注这篇关于的帖子Bulk Mutates
,并创建一个同步批处理,我会得到一个未定义的符号,我该:Mutate
如何解决这个问题?或者让这段代码工作?
class ServiceWrapper:
"""Wraps GoogleAdsService API request"""
# public properties ...
def __init__(self, client, customer_id):
self._client = client
self._ga_service = client.get_service("GoogleAdsService")
self._ad_group_ad_service = client.get_service("AdGroupAdService")
self._batch_job_service = client.get_service("BatchJobService")
self._customer_id = customer_id
self._batch_job_operation = self._create_batch_job_operation(client)
self._batch_job_resource_name = self._create_batch_job(self._batch_job_service, customer_id,
self._batch_job_operation)
def build_removal_operation_sync(customer_id, ad_group_id, ad_id):
mutate_operation1 = serviceWrapper.client.operation(:Mutate)
"""Removes the specified ad"""
resource_name = serviceWrapper.ad_group_ad_service.ad_group_ad_path(
customer_id, ad_group_id, ad_id
)
ad_group_ad_operation = serviceWrapper.client.get_type("AdGroupAdOperation")
ad_group_ad_operation.remove = resource_name
mutate_operation1.ad_group_ad_operation = campaign_operation