17. Exception Handling¶
Properly handling exceptions helps you build plugins that don’t crash or produce unintended side-effects when the user or your code does something you did not expect. Combined with logging, exceptions also allow you to get visibility of areas in which your bot is failing and ultimately address problems to improve user experience.
Exceptions in Errbot plugins should be handled slightly differently from how exceptions are normally used in Python. When an unhandled exception is raised during the execution of a command, Errbot sends a message like this:
Computer says nooo. See logs for details:
<exception message here>
The above is neither helpful nor user-friendly, as the exception message may be too technical or brief (notice there is no traceback) for the user to understand. Even if you were to provide your own exception message, the “Computer says nooo …” part is neither particularly attractive or informative.
When handling exceptions, follow these steps:
trap the exception as you usually would
log the exception inside of the
except
block
self.log.exception('Descriptive message here')
import and use the logging module directly if you don’t have access to
self
self.log
is just a convenience wrapper for the standard Pythonlogging
modulesend a message describing what the user did wrong and recommend a solution for them to try their command again
do not re-raise your exception in the
except
block as you normally would. This is usually done in order to produce an entry in the error logs, but we’ve already logged the exception, and by not re-raising it, we prevent that automatic “Computer says nooo. …” message from being sent
Also, note that there is a errbot.ValidationException
class which you
can use inside your helper methods to raise meaningful errors and handle
them accordingly.
Here’s an example:
from errbot import BotPlugin, arg_botcmd, ValidationException
class FooBot(BotPlugin):
"""An example bot"""
@arg_botcmd('first_name', type=str)
def add_first_name(self, message, first_name):
"""Add your first name if it doesn't contain any digits"""
try:
FooBot.validate_first_name(first_name)
except ValidationException as exc:
self.log.exception(
'first_name=%s contained a digit' % first_name
)
return 'Your first name cannot contain a digit.'
# Add some code here to add the given name to your database
return "Your name has been added."
@staticmethod
def validate_first_name(first_name):
if any(char.isdigit() for char in first_name):
raise ValidationException(
"first_name=%s contained a digit" % first_name
)