I have a number of modules. They all have similar try-except blocks in each file, like this:
from shared.Exceptions import ArgException # and others, as needed
try:
do_the_main_app_here()
except ArgException as e:
Response.result = {
'status': 'error',
'message': str(e)
}
Response.exitcode('USAGE')
# more blocks like the above
with ArgException (and other exceptions) being defined as:
from abc import ABCMeta, abstractmethod
class ETrait(Exception):
__metaclass__ = ABCMeta
#abstractmethod
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
class ArgException(ETrait): pass
Since every module uses similar code to catch exceptions, is there a way to put the exception catching into a shared file that is used by all modules?
I would not do that, but you could create a function in a module like :
from shared.Exceptions import ArgException # and others, as needed
def try_exec(execution_function)
try:
execution_function()
except ArgException as e:
Response.result = {
'status': 'error',
'message': str(e)
}
Response.exitcode('USAGE')
and then call try_exec(do_the_main_app_here) whenever you need to try catch your block of instructions, passing the parameters you need to have the correct context.
The answer is Yes, you can create a module to do that.
The easiest way would be to create a function accepting two parameters: another function with the code that you want to "try" and an "action" to be taken in case of exception.
Then:
def myModuleFunction(tryThisCode, doThis):
try:
returnValue = tryThisCode()
return returnValue
except ArgException as e:
if (doThis == "doThat"):
...
else:
...
Then, after importing your new module, you can use your function like this:
myModuleFunction(divideByZero, 'printMe')
Assuming you have a function called divideByZero();
I hope this helps.
Related
I usually declare a base exception for my modules which does nothing, from that one I derive custom errors that could have additional custom data: AFAIK this is the Right Way™ to use exeptions in Python.
I'm also used to build a human readable message from that custom info and pass it along, so I can refer to that message in error handlers. This is an example:
# this code is meant to be compatible with Python-2.7.x
class MycoolmoduleException(Exception):
'''base Mycoolmodule Exception'''
class TooManyFoo(MycoolmoduleException):
'''got too many Foo things'''
def __init__(self, foo_num):
self.foo_num = foo_num
msg = "someone passed me %d Foos" % foo_num
super(TooManyFoo, self).__init__(msg)
# .... somewhere else ....
try:
do_something()
except Exception as exc:
tell_user(exc.message)
# real world example using Click
#click.command()
#click.pass_context
def foo(ctx):
'''do something'''
try:
# ... try really hard to do something useful ...
except MycoolmoduleException as exc:
click.echo(exc.message, err=True)
ctx.exit(-1)
Now, when I run that code through pylint-2.3.1 it complains about my use of MycoolmoduleException.message:
coolmodule.py:458:19: E1101: Instance of 'MycoolmoduleException' has no 'message' member (no-member)
That kind of code always worked for me (both in Python2 and Python3) and hasattr(exc, 'message') in the same code returns True, so why is pylint complaining? And/or: how could that code be improved?
(NB the same happens if I try to catch the built in Exception instead of my own MycoolmoduleException)
I am working with a class in python that is part of a bigger program. The class is calling different methods.
If there is an error in one of the method I would like code to keep running after, but after the program is finished, I want to be able to see which methods had potential errors in them.
Below is roughly how I am structuring it at the moment, and this solution doesn't scale very well with more methods. Is there a better way to provide feedback (after the code has been fully run) as to which of the method had a potential error?
class Class():
def __init__(self):
try:
self.method_1()
except:
self.error_method1 = "Yes"
break
try:
self.method_2()
except:
self.error_method2 = "Yes"
break
try:
self.method_3()
except:
self.error_method3 = "Yes"
break
Although you could use sys.exc_info() to retrieve information about an Exception when one occurs as I mentioned in a comment, doing so may not be required since Python's standard try/expect mechanism seems adequate.
Below is a runnable example showing how to do so in order to provide "feedback" later about the execution of several methods of a class. This approach uses a decorator function, so should scale well since the same decorator can be applied to as many of the class' methods as desired.
from contextlib import contextmanager
from functools import wraps
import sys
from textwrap import indent
def provide_feedback(method):
""" Decorator to trap exceptions and add messages to feedback. """
#wraps(method)
def wrapped_method(self, *args, **kwargs):
try:
return method(self, *args, **kwargs)
except Exception as exc:
self._feedback.append(
'{!r} exception occurred in {}()'.format(exc, method.__qualname__))
return wrapped_method
class Class():
def __init__(self):
with self.feedback():
self.method_1()
self.method_2()
self.method_3()
#contextmanager
def feedback(self):
self._feedback = []
try:
yield
finally:
# Example of what could be done with any exception messages.
# They could instead be appended to some higher-level container.
if self._feedback:
print('Feedback:')
print(indent('\n'.join(self._feedback), ' '))
#provide_feedback
def method_1(self):
raise RuntimeError('bogus')
#provide_feedback
def method_2(self):
pass
#provide_feedback
def method_3(self):
raise StopIteration('Not enough foobar to go around')
inst = Class()
Output:
Feedback:
RuntimeError('bogus') exception occurred in Class.method_1()
StopIteration('Not enough foobar to go around') exception occurred in Class.method_3()
I have a requirement to execute multiple Python statements and few of them might fail during execution, even after failing I want the rest of them to be executed.
Currently, I am doing:
try:
wx.StaticBox.Destroy()
wx.CheckBox.Disable()
wx.RadioButton.Enable()
except:
pass
If any one of the statements fails, except will get executed and program exits. But what I need is even though it is failed it should run all three statements.
How can I do this in Python?
Use a for loop over the methods you wish to call, eg:
for f in (wx.StaticBox.Destroy, wx.CheckBox.Disable, wx.RadioButton.Enable):
try:
f()
except Exception:
pass
Note that we're using except Exception here - that's generally much more likely what you want than a bare except.
If an exception occurs during a try block, the rest of the block is skipped. You should use three separate try clauses for your three separate statements.
Added in response to comment:
Since you apparently want to handle many statements, you could use a wrapper method to check for exceptions:
def mytry(functionname):
try:
functionname()
except Exception:
pass
Then call the method with the name of your function as input:
mytry(wx.StaticBox.Destroy)
I would recommend creating a context manager class that suppress any exception and the exceptions to be logged.
Please look at the code below. Would encourage any improvement to it.
import sys
class catch_exception:
def __init__(self, raising=True):
self.raising = raising
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
if issubclass(type, Exception):
self.raising = False
print ("Type: ", type, " Log me to error log file")
return not self.raising
def staticBox_destroy():
print("staticBox_destroy")
raise TypeError("Passing through")
def checkbox_disable():
print("checkbox_disable")
raise ValueError("Passing through")
def radioButton_enable():
print("radioButton_enable")
raise ValueError("Passing through")
if __name__ == "__main__":
with catch_exception() as cm:
staticBox_destroy()
with catch_exception() as cm:
checkbox_disable()
with catch_exception() as cm:
radioButton_enable()
A temporary exception class is defined dynamically using 'type' in a python script meant to be used as module. When an instance of this class is caught in importing script it doesn't recognize the class.
Below is code snippet
# the throwing module, defines dynamically
def bad_function():
ExceptionClass = type( "FooBar", (Exception,),
{ "__init__": lambda self, msg: Exception.__init__(self, msg) })
raise ExceptionClass("ExceptionClass")
the using code
import libt0
try:
libt0.bad_function()
#except libt0.FooBar as e:
#print e
except Exception as e:
print e
print e.__class__
can it be explained why libt0.FooBase is not visible to this script? observer output of last line.
It's not clear how you expect FooBar to exist without doing something like this
def bad_function():
ExceptionClass = type( "FooBar", (Exception,),
{ "__init__": lambda self, msg: Exception.__init__(self, msg) })
globals()['FooBar'] = ExceptionClass
raise ExceptionClass("ExceptionClass")
You created the class inside a function, so it doesn't exist as a name in the module's global namespace. In fact, it doesn't exist at all except while bad_function is executing. It's the same reason why this fails:
# file1.py
def good_function():
x = 2
# file2.py
import file1
print file1.x
Your exception class is just a local variable inside bad_function.
I am using flask-auth, which provides some helper decorators. I've added all the various methods below, but the question I want to ask is how to catch any issues thrown by the authorized_handler decorator. It's a general question about decorators, but I thought a real example might help.
If the decorator blows up, how could I catch it?
import os
import flask
import flask_oauth
CONSUMER_KEY = os.environ['CONSUMER_KEY']
CONSUMER_SECRET = os.environ['CONSUMER_SECRET']
oauth = flask_oauth.OAuth()
twitter = oauth.remote_app(
'twitter',
base_url='https://api.twitter.com/1/',
request_token_url='https://api.twitter.com/oauth/request_token',
access_token_url='https://api.twitter.com/oauth/access_token',
authorize_url='https://api.twitter.com/oauth/authenticate',
consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET
)
app = flask.Flask(__name__)
#app.route('/login')
def login():
return twitter.authorize(
callback=url_for(
'oauth_authorized',
next=request.args.get('next') or request.referrer or None)
)
#app.route('/oauth-authorized')
# what happens if this raises an error?
#twitter.authorized_handler
def oauth_authorized(resp):
print 'foo-bar'
Function definitions are executed. Therefore, assuming the exception raised is specific to that decorator, you can wrap the function definition, including decorators, in a try/except:
try:
#app.route('/oauth-authorized')
#twitter.authorized_handler
def oauth_authorized(resp):
print 'foo-bar'
except WhateverError as e:
print "twitter.authorized_handler raised an error", e
Of course, this will leave oauth_authorized undefined if the exception is raised. This is probably OK in your case since you probably don't want it to be be routed anyway. But if this isn't what you want, you could add a dummy definition to your except block.
Or, since decorators are just functions (well, any callable) and the # notation is merely syntactic sugar for a function call, you can wrap just the authorized_handler decoration in try/except:
def oauth_authorized(resp):
print 'foo-bar'
try: # apply decorator
oauth_authorized = twitter.authorized_handler(oauth_authorized)
except Exception as e:
print "twitter.authorized_handler raised an error", e
else: # no error decorating with authorized_handler, apply app.route
oauth_authorized = app.route('/oauth-authorized')(oauth_authorized)
This will leave you with the undecorated version of the function if the authorized_handler decoration fails, but it will not be routed. You could even put the above in its own function and use it as a decorator!