Iteratory strumienia odpowiedzi

Metoda search_stream zwraca iterator obiektów SearchGoogleAdsStreamResponse.

Iterowanie odpowiedzi strumieniowych

Możesz przechodzić przez kolejne obiekty GoogleAdsRow w polu results każdej odpowiedzi, jak pokazano w tym przykładowym kodzie:

def main(client: GoogleAdsClient, customer_id: str) -> None:
    ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService")

    query: str = """
        SELECT
          campaign.id,
          campaign.name
        FROM campaign
        ORDER BY campaign.id"""

    # Issues a search request using streaming.
    stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream(
        customer_id=customer_id, query=query
    )

    for batch in stream:
        rows: List[GoogleAdsRow] = batch.results
        for row in rows:
            print(
                f"Campaign with ID {row.campaign.id} and name "
                f'"{row.campaign.name}" was found.'
            )
      

Struktura każdego elementu GoogleAdsRow jest określana przez pola wybrane w zapytaniu w języku Google Ads Query Language (GAQL). Więcej informacji o strukturze odpowiedzi znajdziesz w artykule Język zapytań Google Ads.

Zachowaj iterator w zakresie.

Podczas wywoływania funkcji GoogleAdsService.search_stream zwracany jest iterator odpowiedzi strumieniowej. Ten iterator musi pozostać w tym samym zakresie co klient GoogleAdsService podczas używania, aby uniknąć uszkodzonych strumieni lub błędów segmentacji. Dzieje się tak, ponieważ bazowy obiekt gRPC Channel jest usuwany przez moduł odzyskiwania pamięci, gdy otwarty obiekt GoogleAdsService wykracza poza zakres. Jeśli obiekt GoogleAdsService nie jest już w zakresie, gdy następuje iteracja wyniku search_stream, obiekt Channel może być już zniszczony, co powoduje niezdefiniowane zachowanie, gdy iterator próbuje pobrać następną wartość.

Poniższy kod pokazuje nieprawidłowe użycie iteratorów strumienia:

def stream_response(client, customer_id, query):
    # The GoogleAdsService instance goes out of scope when this function
    # returns.
    ga_service = client.get_service(
        "GoogleAdsService", version="v26"
    )
    return ga_service.search_stream(customer_id=customer_id, query=query)


def main(client, customer_id):
    query = "SELECT campaign.name FROM campaign LIMIT 10"
    response = stream_response(client, customer_id, query=query)

    # Accessing the iterator in a different scope from where the service object
    # was created results in undefined behavior.
    for batch in response:
        print(batch)

W tym kodzie obiekt GoogleAdsService jest tworzony w innym zakresie niż ten, w którym uzyskiwany jest dostęp do iteratora. W rezultacie obiekt Channel może zostać zniszczony, zanim iterator wykorzysta całą odpowiedź.

Zamiast tego przechowuj iterator strumieniowy w tym samym zakresie co klient GoogleAdsService, dopóki jest używany:

def main(client, customer_id):
    ga_service = client.get_service(
        "GoogleAdsService", version="v26"
    )
    query = "SELECT campaign.name FROM campaign LIMIT 10"
    response = ga_service.search_stream(customer_id=customer_id, query=query)

    # Access the iterator in the same scope where the service object was
    # created.
    for batch in response:
        print(batch)