איטרטורים לסטרימינג

השיטה search_stream מחזירה איטרטור של אובייקטים מסוג SearchGoogleAdsStreamResponse.

אפשר לחזור על הפעולה לכל GoogleAdsRow בשדה results של כל תגובה, כמו בדוגמת הקוד הזו.

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

המבנה של כל GoogleAdsRow נקבע לפי השדות שבוחרים בשאילתת Google Ads Query Language‏ (GAQL). פרטים נוספים על מבנה התגובה זמינים במאמר בנושא שפת השאילתות של Google Ads.

כשמפעילים את הפונקציה GoogleAdsService.search_stream, מוחזר איטרטור של תשובה שמוצגת באופן שוטף. כדי למנוע זרמים שבורים או שגיאות פילוח, צריך להשתמש באיטרטור הזה באותו היקף כמו הלקוח GoogleAdsService. הסיבה לכך היא שאובייקט gRPC  עובר איסוף אשפה ברגע שהאובייקט  הפתוח יוצא מהתחום שלו. אם האובייקט GoogleAdsService כבר לא נמצא בהיקף כשהאיטרציה מתרחשת על התוצאה של search_stream, יכול להיות שהאובייקט Channel כבר נהרס, ולכן תהיה התנהגות לא מוגדרת כשהאיטרטור ינסה לאחזר את הערך הבא.

הקוד הבא מדגים שימוש לא נכון באיטרטורים של סטרימינג:

def stream_response(client, customer_id, query):
    return client.get_service("GoogleAdsService", version="v25").search_stream(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)
    # Access the iterator in a different scope from where the service object was created.
    try:
        for batch in response:
            # Iterate through response, expect undefined behavior.

בדוגמה הזו, האובייקט GoogleAdsService נוצר בהיקף שונה מזה שבו מתבצעת הגישה לאיטרטור. כתוצאה מכך, יכול להיות שהאובייקט Channel ייהרס לפני שהאיטרטור יצרוך את כל התגובה.

במקום זאת, האיטרטור של הסטרימינג צריך להישאר באותו היקף כמו הלקוח GoogleAdsService כל עוד הוא בשימוש:

def main(client, customer_id):
    ga_service = client.get_service("GoogleAdsService", version="v25")
    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 as where the service object was created.
    try:
        for batch in response:
            # Successfully iterate through response.