try/except and descision making - python

I am working on a function which takes different kinds of date_formats as an argument and dispatches it to a function, which is in charge for parsing this format
In other words:
def parse_format(date_format):
# descision making happens here
try:
from_timestamp(date_format)
except:
pass
try:
from_dateformat(date_format)
except:
pass
def from_timestamp(format):
# raise if not in charge
def from_dateformat(format):
# raise if not in charge
def from_custom_format(format):
# raise if not in charge
Currently, parse_format has multiple try/except blocks. Is this the way to go, or is there a more obvious way to do it? Furthermore, how do I handle the case, where every function call fails?

I would do something like this:
class UnrecognizedFormatError(Exception):
pass
def parse_format(date_format):
methods = (from_timestamp, from_dateformat)
for method in methods:
try:
return method(date_format)
except:
pass
raise UnrecognizedFormatError
But also some key points:
except without a specific exception is bad, because a exception can be thrown from unexpected places, such as running out of memory, or a keyboard interrupt in a script. So please use the except SomeException as e form, and use a specific exception type.
If every function fails, this code will throw a UnrecognizedFormatError, allowing the function's user to respond appropriately.

Well, I would look at this as a great place for try/except/else/finally - the else catching your final case where every function call fails, and the 'finally' being run whatever happens in your try/except statements. If your exceptions are appropriately chosen, then it will pick the right function for you.
Also, I'm guessing that this is a learning exercise, as the activity you're describing would be better done in date.strftime()
def from_timestamp(format):
# raise if not in charge
def from_dateformat(format):
# raise if not in charge
def from_custom_format(format):
# raise if not in charge
def parse_format(date_format):
# decision making happens here
try:
from_timestamp(date_format)
except(FirstException):
from_dateformat(date_format)
except(SecondException):
from_custom_format(date_format)
else:
whatever_you_do_if_it_all_goes_wrong()
finally:
thing_that_happens_regardless_of_what's_called()

Related

Try / Except all Python errors of a certain type

In my Python code, I'm using the PyQt5 module to display a GUI. Sometimes, I encounter a Runtime Error if I delete an element then attempt to use a function on the element's instance. This error is only displayed in the console, and it does not actually interfere with the GUI or terminate it.
Regardless, I would like to remove it (the Runtime Errors). My first thought was to use a try/except block on the code, and except the Runtime Error that I was talking about. The problem with this, is that if I encase my whole code with the try/except block, then if the error is caught, it will skip over to the end of my program and terminate:
try:
# If any errors occur here...
<code>
except RuntimeError:
# The GUI will stop entirely, and the Python interpreter will skip to this line
pass
Another solution to my problem is to encase any instance which could throw a RuntimeError with a try/catch block, like so:
try:
# If any errors occur here...
<code that may print an error>
except RuntimeError:
# Python wont display the error
pass
However given the mass amount of times I would need to do this in my code, I was wondering if there was a more efficient way of fixing this problem.
As per my comment, I would definitely go with the catch in the specific line calls that might throw the runtime error. This avoids you accidentally suppressing another error you were not anticipating.
Depending on what the calls are that might give the runtime error, I would prefer a decorator pattern to hide the try-except logic. Something like:
from functools import wraps
def catch_runtime_error(func):
#wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except RuntimeError:
pass # or whatever handle you fancy
return wrapper
which you would then use like:
#catch_runtime_error
def the_function_that_raises(...):
# whatever the body is
the_function_that_raises(...)
Alternatively you can use it more directly in your code:
def the_function_that_raises(...):
# whatever the body is
catch_runtime_error(the_function_that_raises)(...)
You can use customs decorators to to this (I don't know your python level but it's not the most beginner friendly thing). For example, this code here do not raise any error:
from functools import wraps
def IgnoreError(f):
#wraps(f)
def wrapper():
try:
f()
except ZeroDivisionError:
pass
return wrapper
#IgnoreError
def func1():
x = 5/0
func1()
In your case, you will have to define this function:
def IgnoreError(f):
def wrapper(*args, **kwargs):
try:
f(*args, **kwargs)
except RuntimeError:
pass
return wrapper
and then anytime you create a function that may raise the RuntimeError, just put the decorator #IgnoreError before your definition like this:
#IgnoreError
def func():
<your code here>
(if you want here's a video from TechWithTim explaining the decorators)

Should the try/except be placed in the function declaration or call?

Both these snippets do the same thing:
Try/except in function declaration:
def something():
try:
# code goes here
except:
print("Error")
sys.exit(1)
something()
Try/except in function call:
def something():
# code goes here
try:
something()
except:
print("Error")
sys.exit(1)
Is there one that is better/more Pythonic/recommended by PEP8 or is it just up to personal preference? I understand that the second method would get tedious and repetitive if the function needs to be called more than once, but assuming the function is only called once, which one should I use?
the general rule is "only catch exceptions you can handle", see here for an explanation
note that an uncaught exception (in most languages) will cause the program to exit with an unsuccessful status code (i.e. your sys.exit(1)), it will probably also print out a message saying that an exception occurred. your demo therefore is emulating default behaviour, but doing it worse
further, you're catching every exception and this is generally bad style, e.g. you'll implicitly catch SystemExit and other internal exceptions that you probably shouldn't be dealing interacting with

Re-raise and re-catch error immediately in python

I have some exception handling code in python where two exceptions can be raised, the first one being a "superset" of the second one.
I.e. the following code summarizes what I need to do (and works fine)
try:
normal_execution_path()
except FirstError:
handle_first_error()
handle_second_error()
except SecondError:
handle_second_error()
But it requires me to abstract everything into independent functions for the code to remain clean and readable. I was hopping for some simpler syntax like:
try:
normal_execution_path()
except FirstError:
handle_first_error()
raise SecondError
except SecondError:
handle_second_error()
But this does not seem to work (SecondError does not get re-catched if it is raised inside this block). Is there anything doable in that direction though ?
If you wish to manually throw the second error to be handled, you can use nested try-catch blocks like these:
try:
normal_execution_path()
except FirstError:
try:
handle_first_error()
raise SecondError
except SecondError:
handle_second_error()
except SecondError:
handle_second_error()
Perhaps it is worth reviewing the code architecture. But for your particular case:
Create a generic class that handles this type of error. To inherit from it for the first and second error cases. Create a handler for this type of error. In the handler, check the first or second special case and process it with a waterfall.
class SupersetException(Exception):
pass
class FirstError(SupersetException):
pass
class SecondError(SupersetException):
pass
def normal_execution_path():
raise SecondError
def handle_superset_ex(state):
# Our waterfall
# We determine from whom the moment to start processing the exception.
if type(state) is FirstError:
handle_first_error()
# If not the first, the handler above will be skipped
handle_second_error()
try:
normal_execution_path()
except SupersetException as state:
handle_superset_ex(state)
Then just develop the idea.

Is there an alternative for sys.exit() in python?

try:
x="blaabla"
y="nnlfa"
if x!=y:
sys.exit()
else:
print("Error!")
except Exception:
print(Exception)
I'm not asking about why it is throwing an error. I know that it raises exceptions.SystemExit. I was wondering if there was another way to exit?
os._exit() will do a low level process exit without SystemExit or normal python exit processing.
Some questions like that should really be accompanied by the real intention behind the code. The reason is that some problems should be solved completely differently. In the body of the script, the return can be used to quit the script. From another point of view, you can just remember the situation in a variable and implement the wanted behaviour after the try/except construct. Or your except may test more explicit kind of an exception.
The code below shows one variation with the variable. The variable is assigned a function (the assigned function is not called here). The function is called (via the variable) only after the try/except:
#!python3
import sys
def do_nothing():
print('Doing nothing.')
def my_exit():
print('sys.exit() to be called')
sys.exit()
fn = do_nothing # Notice that it is not called. The function is just
# given another name.
try:
x = "blaabla"
y = "nnlfa"
if x != y:
fn = my_exit # Here a different function is given the name fn.
# You can directly assign fn = sys.exit; the my_exit
# just adds the print to visualize.
else:
print("Error!")
except Exception:
print(Exception)
# Now the function is to be called. Or it is equivalent to calling do_nothing(),
# or it is equivalent to calling my_exit().
fn()

Python: Try/Except around whole module

I have a python module containing functions and a few classes. This module is basically used as a tool-set by several of my co-workers.
I want to set-up a sort of bug reporting system where anytime someone generates an exception that I don't handle, an email will be sent with information on the exception. This way I can continually improve the robustness of my code and the help-fullness of my own error messages. Is the best way to do this to just put a try/except block around the entire module?
There are several reasons I think your approach might not be the best.
Sometimes exceptions should be thrown. For example, if I pass some stupid argument to a function, it should complain by throwing an exception. You don't want to get an email every time someone passes a string instead of an integer, etc. do you?
Besides, wrapping the entire thing in a try...except won't work, as that will only be catching exceptions that would occur during the definition of the classes/functions (when your module is loaded/imported). For example,
# Your python library
try:
def foo():
raise Exception('foo exception')
return 42
except Exception as e:
print 'Handled: ', e
# A consumer of your library
foo()
The exception is still uncaught.
I guess you can make your own SelfMailingException and subclass it. Not that I would recommend this approach.
another option:
def raises(*exception_list):
def wrap(f):
def wrapped_f(*x, **y):
try:
f(*x, **y)
except Exception as e:
if not isinstance(e, tuple(exception_list)):
print('send mail')
# send mail
raise
return wrapped_f
return wrap
usage:
#raises(MyException)
def foo():
...

Categories

Resources