Assume I have the following script:
def do_not_call_on_one(i):
if i == 1:
raise ValueError("You never listen.")
print "Success!"
do_not_call_on_one(1)
On excution, you will see the following traceback:
Traceback (most recent call last):
File "test.py", line 7, in <module>
do_not_call_on_one(1)
File "test.py", line 3, in do_not_call_on_one
raise ValueError("You never listen.")
ValueError: You never listen.
Is there some way to manipulate the call stack, such that the error is emitted from the line which is actually causing the problem, like so?:
Traceback (most recent call last):
File "test.py", line 7, in <module>
do_not_call_on_one(1)
ValueError: You never listen.
This would save developer time that would otherwise be wasted scanning the call stack, searching for the incorrectly used function, when the correct behavior could be defined ahead of time.
Is there anything in Python that would allow an exception to use a modified traceback?
There are buitins which are replicating this functionality:
# In test.py:
int('a')
# Executing 'python test.py' yields:
Traceback (most recent call last):
File "test.py", line 1, in <module>
int('a')
ValueError: invalid literal for int() with base 10: 'a'
Note: The traceback does not descend into the int()
function to display a bunch of useless scopes (especially the unhelpful raise ValueError
itself).
tl;dr: probably yes, but I can't imagine that it's a good idea.
I'm going to assume that we could, if we tried hard enough, fake up a callstack to show an exception coming from a different place. But I don't think that's a good idea.
In the first place, it's generally understood that the function which raises an exception is not always at fault. If somebody broke the contract and passed you a parameter which you don't expect, it's okay to raise an exception. If this is intended to cover your ass by raising the exception in the caller's scope so nobody blames your function, I think that somebody (maybe you, maybe your automated testing's "blame" system) needs to re-think how they determine responsibility.
In the second place, I don't think you can define the "right" scope very well. You might imagine that it should always be raised in your caller's scope, because clearly it's not your fault. Well, what if it's not their fault either? Should every function just throw up their hands and say "wasn't my fault" when an exception occurs? Pretty soon our stacktraces will say nothing at all.
Even if you're right, and your function is blameless, you're about to make everybody else's life hell, because manipulating the callstack to hide your function will make everybody scratch their heads, and remove valuable evidence for debugging the situation.
This might seem like a good idea, but I don't think it is, and I think if you put yourself in someone else's shoes you could understand how difficult it would make their life to try to use a function that behaved this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With