Python - Implementing Custom exceptions - python

I have a project that I need to run and have no idea how to implement custom exceptions. It mostly does complicated scientific functions, to be vague.
Mostly it will be raising exceptions if something is not set. I've been given this as a starting example from runnables.
# Define a class inherit from an exception type
class CustomError(Exception):
def __init__(self, arg):
# Set some exception infomation
self.msg = arg
try:
# Raise an exception with argument
raise CustomError('This is a CustomError')
except CustomError, arg:
# Catch the custom exception
print 'Error: ', arg.msg
I have no idea how this is meant to work or how I am meant to implement my code. It's not very explicit.
To give an idea of a basic exception that needs created.
In a function:
if self.humidities is None:
print "ERROR: Humidities have not been set..."
return
Apparently this needs to raise/throw an exception instead.

A ValueError looks suitable for your humidities example.
if self.humidities is None:
raise ValueError('Humidities value required')
If you want to be specific:
class HumiditiesError(Exception):
pass
def set_humidities(humidities):
if humidities is None:
raise HumiditiesError('Value required')
try:
set_humidities(None)
except HumiditiesError as e:
print 'Humidities error:', e.message
This defines a subclass of Exception named HumiditiesError. The default behavior seems sufficient for your example, so the body of the class is empty (pass) as no additional nor modified functionality is required.
N.B. Python 2 assumed. In Python 3 you would access elements of the e.args tuple.

Related

What's the proper way to reraise a custom exception?

If I have the function,
def parse_datetime(s, **kwargs):
""" Converts a time-string into a valid
:py:class:`~datetime.datetime.DateTime` object.
Args:
s (str): string to be formatted.
``**kwargs`` is passed directly to :func:`.dateutil_parser`.
Returns:
:py:class:`~datetime.datetime.DateTime`
"""
if not s:
return None
try:
ret = dateutil_parser(s, **kwargs)
except (OverflowError, TypeError, ValueError) as e:
logger.exception(e, exc_info=True)
raise SyncthingError(*e.args)
return ret
What's the most correct way to raise the caught exception as the common library exception? (SyncthingError(Exception) ) The way it's written right now does not work correctly.
In Python 3 the exceptions can be chained,
raise SyncthingError("parsing error") from e
will produce a stack trace with details of the original exception.
There are examples in the raise statement docs.
You should be able to raise it as long as constructer of the common library exception takes Error or Exception. For example:
Class LibraryException(Exception)...
Class LibraryException(Error)...

Python custom exception and sub-exceptions

What is a good way of raising sub-exceptions (is that's the term)?
Scenario:
I want to raise a custom ConnectivityException when http or ftp exception occurs. Is there any way to raise ConnectivityException such that exceptions are categorized properly (i.e. I should be able to tell if ConnectivityException is raised because of http ot ftp)?
A standard technique would be to subclass ConnectivityException to create exception classes specific to each kind of error condition:
class ConnectivityException(Exception): pass
class HTTPConnectivityException(ConnectivityException): pass
class FTPConnectivityException(ConnectivityException): pass
Then instead of raise ConnectivityException you can use raise HTTPConnectivityException or raise FTPConnectivityException, depending on which specific type of error you want to indicate.
Multiple exception blocks can be used to dispatch error handling according to the exception type:
try:
some_network_operation()
except HTTPConnectivityException as ex:
# This will execute if the error is an HTTPConnectivityException.
except FTPConnectivityException as ex:
# Likewise for FTPConnectivityException.
except ConnectivityException as ex:
# The generic case; this block will execute if the ConnectivityException isn't
# an instance of one of the earlier specified subclasses.
Note that the exception-handling blocks are tried in lexical order; the first block specifying a class to which the exception object belongs will be used. In this case, that means that you need to put the ConnectivityException block last, or else it will catch HTTPConnectivityException and FTPConnectivityException as well.
you can add an attribute named 'source' to ConnectivityException, and set it to 'http' or 'ftp' according to specific situation, when catch ConnectivityException, check the source attribute and decide what to do
here i recommend another way which uses inherit class
class ConnectivityException(Exception):
pass # you can define some attributes and methods, here I just escape
class HTTPConnectivityException(ConnectivityException):
pass
class FTPConnectivityException(ConnectivityException):
pass
def func():
if some_condition:
raise HTTPConnectivityException()
if some_other_condition:
raise FTPConnectivityException()
def another_func():
try:
func()
except HTTPConnectivityException as e:
pass # you can do something here
except FTPConnectivityException as e:
pass

python calling custom exceptions from if-statement and try-except

So, I've created a custom exception that I want to call in 2 different ways (a if/else statement, and a try/except statement). Here is the custom exception:
class CustomException(Exception):
def __init__(self, value=None, *args, **kwargs):
self.parameter = value
for key, value in kwargs.items():
setattr(self, key, value)
for key, value in self.__dict__.items():
print "%s => %s" % ( key, value )
def __str__(self):
return repr(self.parameter)
Here is how I am wanting to implement the custom exception:
try:
if something:
#make an error
;lsdfj
else:
raise CustomException('this is my custom message', file='somefile.txt', var2='something')
except Exception, e:
raise CustomException(e)
My issues, I believe, are two fold:
1: When the standard NameError that is thrown in the try/except block (due to ;lsdfj), I want to pass CustomExceptions some extra parameters like 'file', just like the if/else implementation; how would I do that?
2: When the custom exception is raised (from the if/else statement being false), the CustomExceptions class ends up being called twice, because I raise it in the if/else block then it gets raised again within the except: section. I don't know how to get around this.
So, in the above case, I want to call CustomException when the if-statement is not true, and I want to call it when there is a standard exception thrown inside the code block... but currently, if something: evaluates to false then the CustomException will be raised twice...
So I want the custom exception to be used unilaterally throughout my code for if/else conditions, and standard python exceptions...
I know this explanation was convoluted but I'm not sure how else to explain what I'm after... Any help would be much appreciated! Thanks in advance!
In order not to raise the exception twice, you should wrap the try/except block around the if statemnt only, like so:
if something:
try:
#make an error
;fdsfas
except Exception, e:
raise CustomException(e.message, file='somefile.txt', var2='something')
else:
raise CustomException('this is my custom message', file='somefile.txt', var2='something')
And in order to pass the custom exception some parameters you must provide that parameters to the constructor of the class just like you did in the if/else statement.
You could in the except block use:
if not isinstance(e, CustomException): raise CustomException(e)
Edit:
A sys.exc_info() before the raise inside the except will successfully remove the traceback to the source of the exception i.e. NameError.

how to mock an exception call in python?

I have a code like this:
def extract(data):
if len(data) == 3:
a = 3
else:
component = data.split("-")
if len(component) == 3:
a,b,c = component
else:
raise globals.myException("data1", "Incorrect format", data)
return a,b,c
This is a simplified one. I want to mock the exception class globals.myException. I'm doing that:
def test_extract_data_throws_exception(self):
with patch('globals.myException') as mock:
mock.__init__("data1", "Incorrect format", "")
with self.assertRaises(myException):
self.assertEqual(extract(""), (""))
And I always get the error: "TypeError: exceptions must be old-style classes or derived from BaseException, not MagicMock"
EDIT: As #Aaron Digulla suggest, monkey patching is the correct solution. I post the solution to help others.
def test_extract_data_throws_exception(self):
#monkey patching
class ReplaceClass(myException):
def __init__(self, module, message, detail = u''):
pass
globals.myException = ReplaceClass
with self.assertRaises(myException:
self.assertEqual(extract(""), (""))
The reason is raise checks the type of the argument. It must be a string (a.k.a "old style exceptions") or derived from BaseException
Since a mock isn't either, raise refuses to use it.
In this specific case, you either have to raise the exception or use monkey patching (= overwrite the symbol globals.myException in your test and restore it afterwards).

Invalid argument raise exception

How do I test my parameter if it will raise an exception without actually raising it, using try and except?
class MyClass:
def function(parameter):
pass
parameter is an ambiguous function that may raise 1 or more of any exception, for example:
parameter = pow("5", 5)
A TypeError is raised as soon as the function is called and before the function can execute its statements.
In a comment to another answer you said: "parameter is another function; take for example: parameter = pow("5", 5) which raises a TypeError, but it could be any type of function and any type of exception."
If you want to catch the exeption inside your function you have to call the paramenter (which I'm assuming is callable) inside that function:
def function(callable, args=()):
try:
callable(*args)
except:
print('Ops!')
Example:
>>> function(pow, args=("5", 5))
Ops!
This is if you really need to call your "paramenter" inside the function. Otherwise your should manage its behaviour outside, maybe with something like:
>>> try:
... param = pow('5', 5)
... except:
... param = 10
...
>>> param
10
>>> function(param)
In this example, to raise an exception is pow not function, so it's a good practice to separate the the two different call, and wrap with a try-except statement the code that might fail.
From what I can understand, you want to handle the exceptions raised and also inspect what sort of errors were raised for further inspection? Here is one way of doing it.
class Foo(object):
def find_errors(arg):
errors = []
try:
# do something
except TypeError as e:
errors.append(e)
# handle exception somehow
except ValueError as e:
errors.append(e)
# handle exception somehow
# and so on ...
finally:
pass #something here
return errors, ans
Now you can inspect errors and find out what exceptions have been raised.
If you expect the parameter to be a certain type, you can use type(paramter) is parametertype.
For example, if you wanted to verify that 'i' is an int, run instructions if(type(i) is int):
By edit:
try:
pow("5",5)
return 0
except Exception, err:
sys.stderr.write('ERROR: %s\n' % str(err))
return 1
Perhaps what you mean is how to catch the TypeError exceptions caused by invalid function calls?
Like this:
def foo(bar):
pass
foo(1, 2)
You don't catch them in the function and certainly not in the def foo(bar): line.
It's the caller of the function that made an error so that's where you catch the exception:
try:
foo(1, 2)
except TypeError:
print('call failed')

Categories