I have a rather philosophical problem writing Python code. Normally it is considered good style to use as many try-except-else
blocks as necessary to handle all expectable cases. But I find that this is approach sometimes leads to unnecessarily many levels of indentation that makes it difficult to keep the line count below 80 and suggest nonexistent hierarchical structure in the code. I feel I'm missing some sort of "GOTO" statement or similar jump to cope with this. Therefore I'm wondering if I'm missing some coding style, or Python statement, or pattern, to improve my Python code.
I'll put a more concrete example. Let's think I'm defining a function, and I'm within a loop, where various things could go wrong. Each thing is sufficient to make the rest of the code within the loop skippable, which I normally skip with continue
in a way similar to:
def mu_func()
failed = False
for i in range(100):
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #1")
failed = True
continue
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #2")
failed = True
continue
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #3")
failed = True
# some cleanup code at the end of the function
# that depends on the errors raised
return failed
The important thing to note here is that since we are within a loop, the continue
statement saves me from having to use an else
statement to skip the rest of the code if any exception is raised. Therefore the indentation level does not keep growing. Also note that I cannot just exit from the exception handling, because I need to do some cleanup right before returning from the function.
Now note what happens when we are not within a loop:
def mu_func()
failed = False
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #1")
failed = True
else:
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #2")
failed = True
else:
try:
pass
# we try something that might raise an exception
except:
print("something went wrong by reason #3")
failed = True
# some cleanup code at the end of the function
# that depends on the errors raised
return failed
¿See the difference? If want to skip the rest of the code after any exception has been raised, I have to put inside an else
statement everything below, which trivially increases a level of indent from that point on. This not only leads to annoying code where it is difficult to to keep the line count below 80 characters. The worst aspect is that these nested try-except-else
blocks suggest some sort of hierarchy in the code, which is artificial. All exceptions are equally important. This can be easily appreciated in the first example where the order of the try-except
blocks could be nicely exchanged without touching the indent and without affecting the functionality.
Is there a Python statement, or pattern, that allows me to skip the rest of the code once an exception is handled, that precludes me from having to add more and more indent levels? Am I misusing the else
statement? I'm tempted to put everything within a trivial 1-iteration loop so I have access to the continue
statement to perform the jump to the end of block statement that I'm missing.
CodePudding user response:
One approach might be to wrap the for loop with a try-except
block:
def mu_func():
try:
for i in range(100):
# we try something that might raise an exception
action_1()
print("action #1 succeeds")
action_2()
print("action #2 succeeds")
action_3()
print("action #3 succeeds")
except:
print("something went wrong!")
failed = True
else:
failed = False
return failed
If you have other logic in your for loop, I'd suggest wrapping only the logic that might raise an exception:
def mu_func():
for i in range(100):
try:
# we try something that might raise an exception
action_1()
print("action #1 succeeds")
action_2()
print("action #2 succeeds")
action_3()
print("action #3 succeeds")
except:
print("something went wrong!")
failed = True
break
# here we might do other stuff in the loop
...
else:
failed = False
return failed
CodePudding user response:
What about using:
def mu_func()
failed = False
try:
pass
# we try something that might raise an exception
except ExceptionClass1():
print("something went wrong by reason #1")
failed = True
except ExceptionClass2():
print("something went wrong by reason #2")
failed = True
except ExceptionClass3():
print("something went wrong by reason #3")
failed = True
except ExceptionClass4():
print("something went wrong by reason #4")
failed = True
return failed