I get a StopIteration error when not finding a value with generator expressions

Question:

Well, I have a json file that I load in a variable and if the file doesn’t exist, I make a dictionary that will soon become the json file. So good, I’m trying to look for specific elements of this dictionary and that’s why I’m using generator expressions.

This is how I use it:

Data = json.load(open(file)) if isfile("data.json") else {"News": {},"Records": {},"Profiles": []}

name = "asdadsefttytryrty"

get = next(get for get in Data["Profiles"] if get["Name"] == name or get["ID"] == name)

and the dictionary data would be something like this:

{
    "News": {},
    "Records": {},
    "Profiles": [
        {
            "Name": "123rd453",
            "ID": "1",
            "Password": "dfsdfee",
            "Image": "image"
        },
        {
            "Name": "asdadsefttytryrty",
            "ID": "2",
            "Password": "12345",
            "Image": "image"
        }
    ]
}

So okay, this has a problem if the element I’m looking for doesn’t exist: StopIteration

So to check that the element exists, I wanted to do an if-else to perform certain operations, but I couldn’t. So I decided to use try-except as a temporary solution and I don’t think it’s reliable.

Data = json.load(open(file)) if isfile("data.json") else {"News": {},"Records": {},"Profiles": []}

name = "asdadsefttytryrty"
try:
    get = next(get for get in Data["Profiles"] if get["Name"] == name or get["ID"] == name)
    print("exist")
except:
    print("Doesn't exist")

Doing this is correct?

Asked By: DG Nutria

||

Answers:

Don’t make things complicated. You can simply do this:

from os import path

data = {}
name = "asdadsefttytryrty"

if (path.exists("./data.json")):
    with open('data.json') as f:
        data = json.load(f)
else:
    data = {
        "News": {},
        "Records": {},
        "Profiles": []
    }

if name in data["Profiles"]:
    print("Exists")
else:
    print("Doesn't exist")

Use the path.exists() method from os module to check if a certain path exists.

Declaring variables at the start is a good practice.

Answered By: Vanitas

next does raise StopIteration when the given iterator is exhausted, so what you’re doing is basically correct and reliable, with the only thing to add being the specific exception you’re expecting, in order not to catch unexpected exceptions such as KeyboardInterrupt:

try:
    get = next(get for get in Data["Profiles"] if get["Name"] == name or get["ID"] == name)
    print("exist")
except StopIteration:
    print("Doesn't exist")

That said, in this case the code would arguably be cleaner and more readable written with a for-else construct instead:

for get in Data["Profiles"]:
    if name in (get["Name"], get["ID"]):
        print("Exists")
        break
else:
    print("Doesn't exist")
Answered By: blhsing
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.