User defined exception - python [closed] - python-2.7

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am learning how to create userdefined exception in python
import sqlite3
class MyError(Exception):
def __init__(self, value):
self.value = value
try:
conn= sqlite34.connect('database56.sqlite')
print conn
print 'connection established'
except MyError as e:
print 'Error message:', e.value
When I run the above program ,I get the name error
NameError: name 'sqlite13' is not defined
how do I call the user defined exception if there is a failure to connect to the database ? When [except MyError as e:] is replaced by [except:],still the exception block is not called.
Thanks for your help.

Defining an exception doesn't change what exceptions are raised by other modules. If you want your code to use your exception, you have to catch what the other module rasies and then re-raise your own.
import sqlite3
class MyError(Exception):
def __init__(self, value):
self.value = value
try:
conn= sqlite3.connect('database56.sqlite')
print conn
print 'connection established'
except sqlite3.Error as e:
print 'Error message:', e.value
raise MyError('Could not connect to db: ' + e.value)
I've caught the generic sqlite3 error here but you may need to add other exceptions if they are also raised by the module. Exactly what those exceptions are isn't easy to figure out in python. You can read the source, experiment or look around at examples on the net.

I think this is a XY Problem.
In this case, you want to catch a NameError, so you should directly use that in the except statement. If you want to perform actions after catching the error, you should put that actions in the except statement. Some documentation can be found here.
Example:
except NameError as e:
print 'Error message:', e.value
print 'Splite module not loaded'
User-defined errors are for example useful with wrong/unexpected parameters or output. So user-defined errors are useful because you determine the situations when they are raised, which is not necessarily a situation where "python would crash".
Here some documentation about it.
Maybe an example can help clarifying.
Say you have a function when one of the variables is the price of something.
Then you might do:
class NegativePriceException(Exception):
def __init__(self):
print "Price can't be negative!"
raise AttributeError
def calc_price(...):
price = ... #some calculation
if price < 0:
raise NegativePriceException
return price

Related

Refactor try and Except codeblocks in Python

Currently my app is working with several external APIs, and those functions can raise some kind of error, and I would like to be aware of all kind of situations and don't crash my app. In the following piece of code you can see my function, using slack api (it's just an example, not real example), and you can see how I'm creating a space giving the name and the emails. That function can returns several errors, like APIerror, TypeError... etc etc
Also you can see, all the functions in that file, can raise some errors so it is using try and except and try to don't break our app. In the except part, I don't want to do anything special, just return the error or I don't know, raise an custom error. In the future would be cool if I can enqueue that task if something goes wrong.
slack_client.py
def create_space():
try:
slack_api.create.space(spaceName='space name', email=emails)
except (...):
...
def delete_space():
try:
slack_api.delete.space(spaceId=space_id)
except (...):
...
I would like to refactor the try and except part, because I don't want to copy and paste try and except during all my slack_client class, but in case the connection is down, or some parameter is wron, the "Slack" API will raise me an error.
I thought about create a class, to run each function inside try and catch, but it's a bit weird and I will loose the arguments part like "spaceName='space name'", which I think it's really cool and clear.
def execute_func(func, *args):
try:
func(args)
except (..):
...
So would like some help for this kind of situation, because handle external API is not always really easy... (at the moment working with 2 external APIs)
In a previous life I used VAX/VMS and still remember great pleasure at discoverting LIB$SIG_TO_RET which converted a signal to a return value. You can do exactly the same in not many lines of Python, along the lines you indicated
def execute_func(func, *args, **kwargs):
try:
result = func( *args, **kwargs)
return (True, result)
except Exception as exc:
return ( False, exc)
Usage
result = execute_func( func, a1, a2, ... k1=v1, k2=v2, ...)
if result[0]:
func_result = result[1] # if it's useful
...
else:
# it went wrong, deal with the exception
caught_exception = result[1]
print( caught_exception)
You can catch any exception that is thrown and capture it in a variable to log or raise. You could even raise your own custom exception. Something like this should work:
First create your exception:
class CustomSlackException(Exception):
pass
Then raise it when the API you called throws some exception:
try:
slack_api.create.space(spaceName='space name', email=emails)
except Exception as e:
print(e)
raise CustomSlackException("Custom error message!")
Now you can catch your exception and handle it as needed.

Python 'except' fall-through

I was wondering if you could re-raise a (specific) caught exception and have it caught by a later (general) except in the same try-except. As an example, I want to do something with a specific IOError, but if its not the expected IOError then the exception should be handled like any other error. What I initially tried:
try:
raise IOError()
except IOError as ioerr:
if ioerr.errno == errno.ENOENT:
# do something with the expected err
else:
# continue with the try-except - should be handled like any other error
raise
except Exception as ex:
# general error handling code
However, this doesn't work: the raise re-raises the exception outside the context of the try-except.
What would be the pythonic way of writing this to get the desired exception 'fall-through' behaviour?
(I'm aware there was a proposed 'conditional except' that wasn't implemented, which could've solved this)
If you ultimately want it to catch everything, make it do that. Catch first, sieve later. ;)
try:
raise IOError()
except Exception as ex:
if isinstance(ex, IOError) and ex.errno == errno.ENOENT:
# do something with the expected err
# do the rest
I am not an expert in writing pythonically, but I think one obvious approach (if you know that you're expecting one particular kind of exception), would be to use nested exception handling:
try:
try:
raise IOError()
except IOError as ioerr:
if ioerr.errno == errno.ENOENT:
# do something with the expected err
else:
# pass this on to higher up exception handling
raise
except Exception as ex:
# general error handling code
I know in your comment that you didn't want nested else's -- I don't know if nested exception handling is as bad in your book, but at the very least you can avoid code duplication.
So, I'm working on the same here, and after reviewing the available solutions, I'm going to go with catching the parent exception, and then testing for specifics. In my case I'm working with the dns module.
try:
answer = self._resolver.query(name, 'NS')
except dns.exception.DNSException, e: #Superclass of exceptions tested for
if isinstance(e, dns.resolver.NXDOMAIN):
#Do Stuff
elif isinstance(e, dns.resolver.NoAnswer):
# Do other stuff
else:
# Do default stuff

Assert that logging has been called with specific string

I'm trying to use unittest to test some functions of a SimpleXMLRPCServer I made. Togethere with Mock, I'm now trying to assert that a specific message has been logged when an if statement is reached, but I can't get it to work. I've tried implementing various answers I found here on StackOverflow or by Googling, but still no luck. The calls I make in the Test Case are as follows:
def test_listen_for_tasks(self):
el = {'release': 'default', 'component': None}
for i in range(50):
self.server._queue.put(el)
ServerThread.listen_for_tasks(self.server, 'bla', 'blabla')
with mock.patch('queue_server.logging') as mock_logging:
mock_logging.warning.assert_called_with('There are currently {}'
' items in the queue'.format(
str(len(self.server._queue.queue))))
The function in the server is as follows:
def listen_for_tasks(self, release, component):
item = {'release': release, 'component': component}
for el in list(self._queue.queue):
if self.is_request_duplicate(el, item):
logger.debug('Already have a request'
' for this component: {}'.format(item))
return
self._queue.put(item, False)
if len(self._queue.queue) > 50:
logger.warning('There are currently {}'
' items in the queue'.format(
str(len(self._queue.queue))))
Any idea why this is not working? I'm new to unit testing in Python and asserting that a logger has done something seems the biggest problem one could face, so I might have screwed up with something really simple in the code. Any kind of help will be greatly appreciated!
EDIT: for completeness, here's the test output and failure:
.No handlers could be found for logger "queue_server"
F
FAIL: test_listen_for_tasks (__main__.TestQueueServer)
Traceback (most recent call last):
File "artifacts_generator/test_queue_server.py", line 46, in test_listen_for_tasks
str(len(self.server._queue.queue))))
File "/home/lugiorgi/Desktop/Code/publisher/env/local/lib/python2.7/site-packages/mock/mock.py", line 925, in assert_called_with
raise AssertionError('Expected call: %s\nNot called' % (expected,))
AssertionError: Expected call: warning('There are currently 51 items in the queue')
Not called
Ran 2 tests in 0.137s
FAILED (failures=1)
Since python 3.4 you can use unittest.TestCase class method assertLogs
import logging
import unittest
class LoggingTestCase(unittest.TestCase):
def test_logging(self):
with self.assertLogs(level='INFO') as log:
logging.info('Log message')
self.assertEqual(len(log.output), 1)
self.assertEqual(len(log.records), 1)
self.assertIn('Log message', log.output[0])
You need to first mock the object, then call the function you want to test.
When mocking the object, you also need to provide the full package and object/function name of the object you are mocking, not a variable name.
Finally, it's often more convenient to use the decorator form of patch.
So, for example:
logger = logging.getLogger(__name__)
def my_fancy_function():
logger.warning('test')
#patch('logging.Logger.warning')
def test_my_fancy_function(mock):
my_fancy_function()
mock.assert_called_with('test')
# if you insist on using with:
def test_my_fancy_function_with_with():
with patch('logging.Logger.warning') as mock:
my_fancy_function()
mock.assert_called_with('test')

Improve upon the try-catch python method

I am basically trying to improve upon Python: try-except as an Expression? with a couple of features
Ability to pass in extra args and kwargs to the "try-except" question. This is because I have a success function which takes in a few parameters
Failure function if callable should be called with the exception argument so it gets a chance to handle it.
Here is a sample code with a test however I am not able to get the last line to work
def method2(exc_class = None):
if exc_class:
raise exc_class()
def method1():
return "Hello world"
def try_except(function, failure, exceptions = [], args = [], kwargs = {}):
"""
Run the given function with args and kwargs. If it throws one of the
exceptions in the list then either return failure or call failure function
"""
try:
return function(*args, **kwargs)
except exceptions or Exception as e:
return failure(e) if callable(failure) else failure
if __name__ == "__main__":
#Prints hello world
print try_except(method1, "Failure")
#Prints Failure great!!
print try_except(method2, "Failure", kwargs = {"exc_class" : ValueError})
# I expect below line to print "Failure" properly but it throws a ValueError
print try_except(method2, "Failure", kwargs = {"exc_class" : ValueError}, exceptions=[ValueError])
My question here is the except exceptions or Exception as e: line does not substitute the list of exceptions properly. I cannot do *exceptions as shown in the original question because I want to take in extra parameters for the function.
I am okay to change the try_except to some extent though.
Note: I have considered doing a catch all except Exception as e and then checking if the exception class in in the list and if it is not then rethrow it. However that won't work because when I rethrow the original stack trace is lost and I do not want to do that.
When catching several exception types with one except clause, you can't use just any iterable object; you must specifically use a tuple. You can still allow try_except to take any iterable as an argument by creating a tuple in the except clause itself.
try:
return function(*args, **kwargs)
except tuple(exceptions or (Exception,)) as e:
return failure(e) if callable(failure) else failure
From the docs:
For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is “compatible” with the exception. An object is compatible with an exception if it is the class or a base class of the exception object, or a tuple containing an item compatible with the exception.

Adding if or try except blok in python function

I got this question i'm a little unsure how to solve:
"There are a NoneType error when reproducing the code. The getaddressdata() returns a None value. This can be fixed by adding an if-statement in the getpricelist() to see if the data is None. Use a try except block to handle invalid data."
Have to fix this before my code can run.
my function / code you see here:
def getpricelist( ):
l1=[]
for line in file('addresslist.txt'):
data=getaddressdata(line.strip( ),'Cambridge,MA')
if data != 'None':
l1.append(data)
return l1
Where do i make the try / except blok??
You should use pythonic idiom is None to check if the variable is of a NoneType or not:
data = getaddressdata(line.strip( ),'Cambridge,MA')
if data is not None:
l1.append(data)
Also see:
not None test in Python
What is the difference between " is None " and " ==None "
Hope that helps.