Highstaker
Highstaker

Reputation: 1075

An if statement to check within try statement in Python, need the code to execute in case an exception is raised as well

I'm a bit stumped here. Here's a piece of Python code:

try:
    if parse[index+1][0] != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]
except IndexError:
    warning("Reached end of file. No next element")
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Basically I want these two actions (addition of individual_services_cur list to individual_services list and clearing of individual_services_cur list) to take place either if the next element in parse is not "5" or if it doesn't exist (basically it is the end of file).

I am wondering if there is a more elegant (maybe even, as they say, "pythonic") way to write this code, for example, without the need to write these two actions twice. I couldn't think of any good solution with finally or else statements, and it seems that I cannot get rid of try statement because once the end of file is reached, the IndexError exception is inevitably raised.

Upvotes: 4

Views: 16841

Answers (5)

Rick
Rick

Reputation: 45231

Another idea:

update_i_s = True

try:
    update_i_s= parse[index+1][0] != "5"
except IndexError:
    warning("Reached end of file. No next element")
finally:
    if update_i_s:
        individual_services.append([individual_services_cur]) if flag
        individual_services_cur=[]

flag=True is only needed for the case that there is only one line in the file, and only needs to be set once at the beginning (so don't go putting it inside any loops).


EDIT:

By the way, if there is a possibility the finally block could fail, you might want to do something like this:

try:
    try:
        update_i_s= parse[index+1][0] != "5"
    except IndexError:
        warning("Reached end of file. No next element")
    finally:
        if update_i_s:
            individual_services.append([individual_services_cur]) if flag
            individual_services_cur=[]
except Exception:
    warning("failed to update individual_services")
    raise

Upvotes: 2

Rick
Rick

Reputation: 45231

Or thinking outside the box a bit:

if index + 1 not in (index for index, value in enumerate(parse) if value[0] == '5'):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

Where (index for index, value in enumerate(parse) if value[0] == '5') is a generator that yields the line number of each line that has a '5' as the first character. It is equivalent to this:

def has_5s(p):
    '''Yield line numbers that begin with a 5'''
    for index, line in enumerate(p):
        yield index if line[0] == '5'

if index + 1 not in has_5s(parse):
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

You are simply checking to see if the following line number (line + 1) is one of these line numbers yielded by the generator. Since enumerate and the generator itself are lazy this should be very fast.

Upvotes: 0

Hugh Bothwell
Hugh Bothwell

Reputation: 56634

How about

last = len(parse) - 1

if index == last or parse[index + 1][0] != "5":
    individual_services.append(individual_services_cur)
    individual_services_cur = []

Upvotes: 0

bondgeek
bondgeek

Reputation: 41

You can use an intermediate variable to perform the checks you need.

try:
    value_to_check = parse[index+1][0]

except IndexError:
    warning("Reached end of file. No next element")
    value_to_check = None
finally:
    if value_to_check != "5":
        individual_services+=[individual_services_cur]
        individual_services_cur=[]

Upvotes: 3

khelwood
khelwood

Reputation: 59113

You could assign a variable in both cases and then check it once.

badstuff = False
try:
    if parse[index+1][0] != "5":
        badstuff = True
except IndexError:
    warning("Reached end of file. No next element")
    badstuff = True

if badstuff:
    individual_services+=[individual_services_cur]
    individual_services_cur=[]

If it suits you, you could put the if badstuff: in a finally block, depending on what the rest of your code is doing.

Alternatively, put the individual_services stuff in a function, and call it in both places.

Upvotes: 1

Related Questions