How to raise an exeption that tells me in what loop I was in?
Question:
I have the following input to an assign_points(lists)
function:
[['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '10', '10', '10', '10', '0', '0', '0', '0', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '10', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']]
And in my code I have something like:
def A(point):
try:
#something
B(val_1, val_2, val_3)
except ValueError:
#It should quit here but I want to say what line and item (Y, X loop) it was in
def B(val_1, val_2, val_3):
try:
...
except ValueError:
#It should quit here but I want to say what line and item (Y, X loop) it was in
def assign_points(lists)
for y, list in enumerate(lists):
for x, point in enumerate(list):
A(point)
I have a function B()
inside of a function A()
inside two for
loops.
If there’s anything wrong inside the function B I want to raise an exception that gives me what loop it was on.
I know I can pass x and y but I feel like it bloats the code and makes it less reusable. I was wondering if there was an alternative to that.
I want the exception to say " item on line is improperly formatted"
Is this possible to do?
Answers:
Neither A nor B know (nor should know) about the outer iteration. But assign_points
knows exactly where it is. Move the exception handling there.
def A(point):
B(val_1, val_2, val_3) # exception raised in here
def B(val_1, val_2, val_3):
... an exception raised here
def assign_points(lists)
for y, list in enumerate(lists):
for x, point in enumerate(list):
try:
A(point)
except ValueError as e:
print(x, y, e)
If you need context information from the lower level functions, they could catch ValueError and reraise with details. Perhaps by adding attributes to the existing exception or creating a new one with the specifics.
For example
class BError(Exception):
def __init__(self, val_1, val_2, val_3):
self.val_1 = val_1
self.val_2 = val_2
self.val_3 = val_3
self.message = f"{val_1}, {val_2}, {val_3} are super bad"
super().__init__(self.message)
def A(point):
B(val_1, val_2, val_3) # exception raised in here
def B(val_1, val_2, val_3):
try:
.... calculation raises ValueError
except ValueError as e:
raise BError(val_1, val_2, val_3)
def assign_points(lists):
x = y = None
try:
for y, list in enumerate(lists):
for x, point in enumerate(list):
A(point)
except BError as e:
print(x, y, e)
There are lots of options here. For instance, perhaps BError should keep the original error message. But you get the idea.
I have the following input to an assign_points(lists)
function:
[['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0', '0', '10', '10', '0', '0'],
['0', '0', '10', '10', '10', '10', '10', '10', '0', '0', '0', '0', '10', '10', '10', '10', '0', '0', '0'],
['0', '0', '0', '10', '10', '10', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '10', '10', '0', '0', '0', '10', '10', '10', '10', '10', '10', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'],
['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']]
And in my code I have something like:
def A(point):
try:
#something
B(val_1, val_2, val_3)
except ValueError:
#It should quit here but I want to say what line and item (Y, X loop) it was in
def B(val_1, val_2, val_3):
try:
...
except ValueError:
#It should quit here but I want to say what line and item (Y, X loop) it was in
def assign_points(lists)
for y, list in enumerate(lists):
for x, point in enumerate(list):
A(point)
I have a function B()
inside of a function A()
inside two for
loops.
If there’s anything wrong inside the function B I want to raise an exception that gives me what loop it was on.
I know I can pass x and y but I feel like it bloats the code and makes it less reusable. I was wondering if there was an alternative to that.
I want the exception to say " item on line is improperly formatted"
Is this possible to do?
Neither A nor B know (nor should know) about the outer iteration. But assign_points
knows exactly where it is. Move the exception handling there.
def A(point):
B(val_1, val_2, val_3) # exception raised in here
def B(val_1, val_2, val_3):
... an exception raised here
def assign_points(lists)
for y, list in enumerate(lists):
for x, point in enumerate(list):
try:
A(point)
except ValueError as e:
print(x, y, e)
If you need context information from the lower level functions, they could catch ValueError and reraise with details. Perhaps by adding attributes to the existing exception or creating a new one with the specifics.
For example
class BError(Exception):
def __init__(self, val_1, val_2, val_3):
self.val_1 = val_1
self.val_2 = val_2
self.val_3 = val_3
self.message = f"{val_1}, {val_2}, {val_3} are super bad"
super().__init__(self.message)
def A(point):
B(val_1, val_2, val_3) # exception raised in here
def B(val_1, val_2, val_3):
try:
.... calculation raises ValueError
except ValueError as e:
raise BError(val_1, val_2, val_3)
def assign_points(lists):
x = y = None
try:
for y, list in enumerate(lists):
for x, point in enumerate(list):
A(point)
except BError as e:
print(x, y, e)
There are lots of options here. For instance, perhaps BError should keep the original error message. But you get the idea.