Reputation: 385
I'm working through a chapter on exceptions in Python and the author gives the following example, some different exceptions are stored in a list, one or none is chosen randomly and handled:
import random
some_exceptions = [ValueError, TypeError, IndexError, None]
try:
choice = random.choice(some_exceptions)
print(f'raising {choice}')
if choice:
raise choice('An Error') # Don't understand the need for the 'An Error' argument
except ValueError:
print('Caught a ValueError')
except TypeError:
print('Caught a TypeError')
except Exception as e:
print(f'Caught some other error: {e.__class__.__name__}')
else:
print('This code is called if there is no exception')
finally:
print('This code is always called')
I don't understand the line raise choice('An Error')
, the words 'An Error' are never output to the console and the example appears to work just as well with that line changed to raise choice()
, is there any specific reason the author did this?
Upvotes: 1
Views: 2302
Reputation: 2430
These both are type errors (in native python), but see how the custom message is different
>>> a = [1,2,3]
>>> a['d']
TypeError: list indices must be integers or slices, not str
>>> 1 in 'fs'
TypeError: 'in <string>' requires string as left operand, not int
And so, to generate a custom error message which is subset of an existing class you can do this:
>>> raise TypeError('meaningless type error')
TypeError: meaningless type error
Upvotes: 1
Reputation: 148965
It is just the common usage. Exceptions (derived from BaseException
) have an args
member which contains the parameters passed at creation time, so they can accept 0 to n parameters. Nevertheless the doc for BaseException.args
says (emphasize mine):
The tuple of arguments given to the exception constructor. Some built-in exceptions (like OSError) expect a certain number of arguments and assign a special meaning to the elements of this tuple, while others are usually called only with a single string giving an error message.
Upvotes: 1
Reputation: 3146
I think you are confused how the raise command works. It takes a class which already has some inbuilt some stuff like an Exception class. It cannot raise exception on any class. If you need to raise that message, go about like
import random
some_exceptions = [ValueError, TypeError, IndexError, None]
try:
choice = random.choice(some_exceptions)
print(f'raising {choice}')
if choice:
raise Exception('An Error') # Don't understand the need for the 'An Error' argument
except ValueError:
print('Caught a ValueError')
except TypeError:
print('Caught a TypeError')
except Exception as e:
print(f'Caught some other error: {e.__class__.__name__}')
else:
print('This code is called if there is no exception')
finally:
print('This code is always called')
Upvotes: 1
Reputation: 5333
Exceptions are classes. If you write your own (deriving e.g. from ValueError) the constructor of instance creation - this is what do by writing ValueError()
- may store this string to be output by the __str__
method of the exception. So if the exception type is insufficient for pinpointing the reason the string argument may prove useful.
Upvotes: 1
Reputation: 392
When you use Try catch in python in this way:
choice = ValueError
try:
raise choice('An Error')
except ValueError as e:
print(e)
You will get "An Error" printed it is useful to customize output error so you can know where the error happened like so:
choice = ValueError
a = int(input("Enter a number a"))
b = int(input("Enter a number b"))
try:
error = "No error"
if a == 0:
error = "a is Null"
if b == 0:
error = "b is Null"
raise choise(error)
except ValueError as e:
print(e)
In this code you can track From where the error comes from if you do for example a division by a or b and you get a Null division error
Upvotes: 1
Reputation: 9044
Exceptions are classes too. the string are parameter passed to the class.
In [10]: help(ValueError)
In [11]: v = ValueError("value is not accepted.")
In [12]: v
Out[12]: ValueError('value is not accepted.')
In [13]: v.args
Out[13]: ('value is not accepted.',)
Upvotes: 4