The `search_stream` method returns an iterator of
[`SearchGoogleAdsStreamResponse`](https://developers.google.com/google-ads/api/reference/rpc/v26/SearchGoogleAdsStreamResponse.md.txt)
objects.

## Iterate through stream responses

You can iterate through each [`GoogleAdsRow`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsRow.md.txt) in
each response's `results` field as shown in the following code example:


```python
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.'
            )
      
```

<br />

The structure of each `GoogleAdsRow` is determined by the fields you select in
your Google Ads Query Language (GAQL) query. For more details about the response
structure, see [Google Ads Query Language](https://developers.google.com/google-ads/api/docs/query/overview.md.txt).

> [!NOTE]
> **Note:** Starting in `google-ads` `v28.4.0`, you can also iterate through stream responses asynchronously using `async for batch in response:` by retrieving an async service client (`client.get_service("GoogleAdsService", is_async=True)`) and awaiting `search_stream()`.

## Keep the iterator in scope

When calling
[`GoogleAdsService.search_stream`](https://developers.google.com/google-ads/api/reference/rpc/v26/GoogleAdsService/SearchStream.md.txt),
a streaming response iterator is returned. This iterator must remain in the same
scope as the `GoogleAdsService` client while being consumed to avoid broken
streams or segmentation faults. This is because the underlying gRPC `Channel`
object is garbage-collected once the open `GoogleAdsService` object goes out of
scope. If the `GoogleAdsService` object is no longer in scope when iteration
occurs on the result of `search_stream`, the `Channel` object may already be
destroyed, causing undefined behavior when the iterator attempts to retrieve the
next value.

The following code demonstrates **incorrect** usage of stream iterators:

```python
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)
```

In this code, the `GoogleAdsService` object is created within a different scope
from where the iterator is accessed. As a result, the `Channel` object may be
destroyed before the iterator consumes the entire response.

Instead, keep the streaming iterator in the same scope as the `GoogleAdsService`
client for as long as it is being used:

```python
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)
```