marcin2x4
marcin2x4

Reputation: 1429

Python - handle empty list when iterating through dict

I have a list of dicts and need to retreive events key which is a list. However that list is not always filled with data, depending on a case.

How to iterate through them and not get list index out of range error? [-1] does work but when events is and empty list, I get that error.

Sample input:

jobs = [
   {
      "JobName":"xyz",
      "JobRunState":"SUCCEEDED",
      "LogGroupName":"xyz",
      "Id":"xyz",
      "events":[
         
      ]
   },
   {
      "JobName":"xyz2",
      "JobRunState":"SUCCEEDED",
      "LogGroupName":"xyz",
      "Id":"xyz",
      "events":[
         {
            "timestamp":1673596884835,
            "message":"....",
            "ingestionTime":1673598934350
         },
         {
            "timestamp":1673599235711,
            "message":"....",
            "ingestionTime":1673599236353
         }
      ]
   }
]

Code:

    success = [
        {
            "name": x["JobName"],
            "state": x["JobRunState"],
            "event": self.logs_client.get_log_events(
                logGroupName=x["LogGroupName"] + "/output",
                logStreamName=x["Id"],
            )["events"][-1]["message"],
        }
        for x in jobs
        if x["JobRunState"] in self.SUCCESS
    ]

Expected behavior: when ["events"] is empty, return "event" as an empty list.

[
    {'name': 'xyz', 'state': 'SUCCEEDED', 'event': []}, 
    {'name': 'xyz2', 'state': 'SUCCEEDED', 'event': "...."}
]

Error code:

"event": self.logs_client.get_log_events(
IndexError: list index out of range

Upvotes: 0

Views: 79

Answers (2)

Kurt
Kurt

Reputation: 1748

The simple answer is to not try to do everything inside a list comprehension. Just make it a regular loop where you can add more complex logic and build your resulting list with append().

successes = list()
for job in jobs:
    if job["state"] in self.SUCCESS:
        success = dict()
        #do stuff to populate success object
        successes.append(success)

Upvotes: 1

Samwise
Samwise

Reputation: 71454

If you actually wanted to get all the events and not just the last one, you could do:

success = [
    {"event": event["message"]}
    for x in jobs 
    for event in self.logs_client.get_log_events(
        logGroupName=x["LogGroupName"] + "/output",
        logStreamName=x["Id"],
    )["events"]
]

which will simply handle empty lists by not producing a dictionary for those jobs.

If you really just wanted the last one, but still to skip jobs with no events, modify the above code to iterate over a slice of either the last event or no events:

success = [
    {"event": last_event["message"]}
    for x in jobs 
    for last_event in self.logs_client.get_log_events(
        logGroupName=x["LogGroupName"] + "/output",
        logStreamName=x["Id"],
    )["events"][-1:]
]

the useful difference of the slice operation being that it gives you a list no matter what rather than an IndexError on an empty list:

>>> [1, 2, 3][-1:]
[3]
>>> [][-1:]
[]

Upvotes: 1

Related Questions