Python: How to kill a infinite for loop?

Viewed 126

I have a for loop that goes into a list that has 10 items. For every item it has it adds 10 more to the list with the for loop. I want to kill the loop once the list length is 100 is this possible or I can't get out of the loop because the list never ends growing?

This is my code:

keywords = [
"apple store",
"applesauce recipe",
"applesauce",
"appleseeds",
"apples to apples",
"apples and honey",
"applesauce cake",
"apple support",
"apples and bananas"
]

   for i in keywords:
            url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
            response = requests.get(url, verify=False)
            suggestions = json.loads(response.text)
            for word in suggestions[1]:
                k = word
                keywords.append(k)
                print(word)

I tried adding the following at the end but no luck


if len(keywords) == 100:
    print('this is where it needs to break')
    break


I see the print message when it hits 100, but it keeps going.

Any idea?

5 Answers

What if len(keywords) is never == 100.
Because keywords.append(k) is in a loop.
Example: len(keywords) == 98 and after loop len(keywords) become 103.

Try to change the if statements to test if len(keywords) is greater or equal than 100.

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    for word in suggestions[1]:
        keywords.append(word)
        print(word)

    if len(keywords) >= 100:  # test if greater or equal than 100
        print('this is where it needs to break')
        break

This is caused by you have 2 loops inside each other so you have to break twice, I don't think this is the most optimized solution, but it does the job:

import requests
import json

keywords = [
"apple store",
"applesauce recipe",
"applesauce",
"appleseeds",
"apples to apples",
"apples and honey",
"applesauce cake",
"apple support",
"apples and bananas"
]

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    if len(keywords) == 100:
        print('this is where it needs to break')
        break
    else:
        for word in suggestions[1]:
            if len(keywords) == 100:
                print('this is where it needs to break')
                break
            else:
                keywords.append(word)
                print(word)

You should avoid modifying the list you're iterating through, because it can lead to strange behaviour. It would be better to have list of queries that haven't been tried out, which you deplete and fill up as you go, and a seperate loop (either for i in range(100) or a while loop with your break condition).

As for the code you showed, there's two options, depending on where you placed the break condition.

Version 1:

Probably what you're doing

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    for word in suggestions[1]:
        k = word
        keywords.append(k)
        print(word)

        if len(keywords) == 100:
            print('this is where it needs to break')
            break

Here, you only break the inner loop. The outer keeps right on going, and so you have an infinite loop, since it keeps hitting the inner loop and then breaking out, again and again, because the outer loop is never terminated.

Version 2:

Which still can easily produce an infinite loop.

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    for word in suggestions[1]:
        k = word
        keywords.append(k)
        print(word)

    if len(keywords) == 100:
        print('this is where it needs to break')
        break

Here, the outer loop would end. However, it might not, because the break condition is badly formulated. Since you can add multiple words in each inner loop, len(keywords) might go from <100 to >100 without ever hitting the condition. And then it never will, and you get an infinite loop again. Instead, it should be len(keywords) >= 100, though then you will have cases where keywords is not exactly 100.

But the real answer is that you shouldn't be modifying the list you're iterating over in the first place, and restructure you're logic accordingly.

Usually it's considered bad practice to modify a list while traversing it. That being said however, this is one way of doing it:

keywords = [
"apple store",
"applesauce recipe",
"applesauce",
"appleseeds",
"apples to apples",
"apples and honey",
"applesauce cake",
"apple support",
"apples and bananas"
]

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    if len(keywords) >= 100:
        print('this is where it needs to break')
        break
    for word in suggestions[1]:
        k = word
        keywords.append(k) if len(keywords) < 100 else 0 # you can put basically anything here insetad of 0
        print(word)

A better way of doing it would be to use a second list and using the extend() function

keywords = [
"apple store",
"applesauce recipe",
"applesauce",
"appleseeds",
"apples to apples",
"apples and honey",
"applesauce cake",
"apple support",
"apples and bananas"
]

new_keywords = list(keywords) # storing a copy of keywords in new_keywords

for i in keywords:
    url = "http://suggestqueries.google.com/complete/search?output=firefox&q=" + i
    response = requests.get(url, verify=False)
    suggestions = json.loads(response.text)
    
    new_keywords.extend(suggestions[1])

you need to check the length before the loop.that will restrict the loop to go on.

Related