Ask Your Question
1

How can I make my code continue despite exception?

asked 2016-03-09 10:21:10 -0600

stan gravatar image

I wrote a function that loops through a data array, performs some calculations and returns new arrays with the results. Unfortunately, some entries in the array contain zero values and cause a division by zero exception, which stops the code. Is there a way to generally ignore division by zero exceptions without wrapping every single line in a "try: except:" construct? Here is a very simplistic example:

var('a x y')
eq_y1 = y == a/x
eq_y2 = y == a*x
eq_y3 = y == a^x

def fun_loop(in_array):
    out_array1 = np.zeros_like(in_array)
    out_array2 = np.zeros_like(in_array)
    out_array3 = np.zeros_like(in_array)
    for i in srange(len(in_array)):
        in_list = in_array[i]
        for j in srange(len(in_list) - 1):
            vdict = {}
            vdict[a] = in_array[i][j]
            vdict[x] = in_array[i][j+1]
            out_array1[i,j] = eq_y1.rhs().subs(vdict)
            out_array2[i,j] = eq_y2.rhs().subs(vdict)
            out_array3[i,j] = eq_y3.rhs().subs(vdict)
    return [out_array1, out_array2, out_array3]
in_array = np.array([[3,2,1],[2,1,3],[-3,-1,-2]])
fun_loop(in_array)

returns: [array([[1, 2, 0], [2, 0, 0], [3, 0, 0]]), array([[6, 2, 0], [2, 3, 0], [3, 2, 0]]), array([[9, 2, 0], [2, 1, 0], [0, 1, 0]])]

However:

in_array = np.array([[3,2,1],[2,1,3],[-3,-1,-2]])
fun_loop(in_array)

returns "ValueError: power::eval(): division by zero" and no results. I would like the function to still return the results for all the other cells, without wrapping each line of the code in a try-except construct. Is there a way to define a general rule how to deal with exeptions of a certain kind within a function like that? The reason is that I have many different equations in the real function and don't want to make the code three times longer.

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
0

answered 2016-03-09 16:11:09 -0600

nbruin gravatar image

You can express "general rules" like this as wrapper functions. In your case you might want to write something along the lines of:

def subs_or_none(expr, vdict):
    try:
        return expr.subs(vdict)
    except ValueError:
        return None

and then you can write

    out_array1[i,j] = subs_or_none(eq_y1.rhs(), vdict)
    ...

Your code is still a bit longer, because you have to specify how to handle the exception (but you really need to do that anyway). Your cost does not go up with the number of times you need the behaviour, however.

Be careful that this code would catch all ValueErrors. You'd need to do some more checking to ensure it's just a division-by-zero. In fact, one could consider it a deficiency that pynac signals a ValueError here and not a ZeroDivisionError.

edit flag offensive delete link more

Comments

Awesome, thank you! This does the trick with only small alterations to the code. Just a small comment, unless insisting on an integer dtype in the array, it would be better to use NaN instead of None. See here for a discussion of NaN vs. None: http://stackoverflow.com/questions/17...

stan gravatar imagestan ( 2016-03-10 06:25:15 -0600 )edit
0

answered 2016-03-09 12:20:13 -0600

calc314 gravatar image

Using an inline if then else statement might do it. Below, I assume the equations involved are rational functions, but it works for that case. You might be able to adapt this idea to your specific situation.

var('a x y')
eq_y1 = y == a/x
eq_y2 = y == a*x
eq_y3 = y == a^x

def fun_loop(in_array):
    out_array1 = np.zeros_like(in_array)
    out_array2 = np.zeros_like(in_array)
    out_array3 = np.zeros_like(in_array)
    for i in srange(len(in_array)):
        in_list = in_array[i]
        for j in srange(len(in_list) - 1):
            vdict = {}
            vdict[a] = in_array[i][j]
            vdict[x] = in_array[i][j+1]
            out_array1[i,j] = eq_y1.rhs().subs(vdict) if eq_y1.rhs().denominator().subs(vdict)!=0 else 0
            out_array2[i,j] = eq_y2.rhs().subs(vdict)
            out_array3[i,j] = eq_y3.rhs().subs(vdict)
    return [out_array1, out_array2, out_array3]
in_array = np.array([[3,2,1],[2,1,3],[-3,-1,-2]])
fun_loop(in_array)
edit flag offensive delete link more

Comments

Thanks, but this is quite similar to wrapping each line in a try-exception statement, only using if-else instead. I was wondering if one could not wrap the whole function in something that would continue evaluation every time a division by zero exception is thrown.

stan gravatar imagestan ( 2016-03-09 16:03:58 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2016-03-09 10:21:10 -0600

Seen: 71 times

Last updated: Mar 09 '16