Reputation: 41
I am editing the question for clarity.
I created a class in a module that imports MySQLdb. I have found that MySQLdb will raise an Exception if the table the user passes to my class does not exist. I am catching that exception, and passing a new one to the client. But even if the client catches my exception, the program still terminates. I have also tried passing to the client the same Exception MySQLdb is giving my class.
Since the client will be calling my method in a loop, passing in various table names, I don't want the program to choke if the table name is bad. I'd like the client's iterations to continue to the next valid table name. Here is a snippet (tableName is an arg pass in to the method):
In my class/module:
self.tableName = tableName try: self.cursor.execute("select * from " + self.tableName + ";") #Will raise Exception if the table does not exist. except: raise MyException("\n*** " + self.tableName + " does not exist. ***")
In the client:
tables = ["BadTableName", "GoodTableNameA", "GoodTableNameB","GoodTableNameC"] try: for table in tables: my_method(table) #Exception message gets passed in with BadTableName, but the program ends. Subsequest iterations of this loop never happen except Exception, e: print e
I would like the client to continue even after calling my_method(BadTableName).
By the way, my_method() is part of a class defined in its own module which the client is importing.
Thank you.
Upvotes: 0
Views: 2759
Reputation: 365697
After reading your edited question, I'm not sure which of two problems you're having.
If your problem is just that you just want an exception to only terminate one loop iteration instead of the whole loop, it's just a matter of re-nesting the statements in the obvious way. Instead of this:
try:
for table in tables:
my_method(table) #Exception message gets passed in with BadTableName, but the program ends. Subsequest iterations of this loop never happen
except Exception, e:
print e
Do this:
for table in tables:
try:
my_method(table) #Exception message gets passed in with BadTableName, but the program ends. Subsequest iterations of this loop never happen
except Exception, e:
print e
On the other hand, if the problem is that the client isn't catching the exception, the problem is most likely that your MyException
isn't a subclass of Exception
. There are at least three ways this could happen.
Since you're using old-style except
syntax (except Exception, e:
) instead of new-style (except Exception as e:
), you may be using an older Python version that lets you raise classes that don't inherit from BaseException
. For example:
class MyException(object):
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
Depending on your Python version, this may fail to raise the MyException
and instead raise a TypeError('
Out[11]: TypeError('exceptions must be old-style classes or derived from BaseException, not MyException')
(which will get caught), or print a warning, or just silently "work" as you asked it to (meaning you don't catch anything, and your program quits with a traceback).
Meanwhile, even in 2.7, you can still raise old-style classes, which also won't get caught:
class MyException:
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
This will always fail to catch the exception, and your app will quit with a traceback.
Finally, if you inherited from BaseException
instead of Exception
, then obviously Exception
won't catch it.
class MyException(BaseException):
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
Once again, this will always fail to catch what you raised, and you'll quit with a traceback.
Upvotes: 0
Reputation: 27762
Adding to the other answers: uncaught exceptions will terminate a program, but only after executing the applicable finally
block (if any) and any atexit
handlers. So in principle, it is possible to continue execution indefinitely after an uncaught exception.
There is no class of exceptions that will just print an error message and continue execution by their nature, though. If you want that, use warnings.
Upvotes: 1
Reputation: 11
An uncaught exception will terminate a program. A caught exception will not
If the exception is caught, the stack trace can be output using the traceback module:
http://docs.python.org/2/library/traceback.html#traceback-examples
Upvotes: 0
Reputation: 55952
Exceptions do not always cause the program to end. From the docs:
Errors detected during execution are called exceptions and are not unconditionally fatal:
If an exception is raised in a try: except block and the except
clause is specifying the exception or a super class of the exception it will be handled.
When handling an exception you can inspect it and find out all information related to it. I have never used the traceback
module before but it looks like it contains everything you need.
I guess your second question depends on what you want your user to see. Should the exception be shown? (you have access to the traceback). Should just the message be shown? SHould you log the traceback?
Upvotes: 1
Reputation: 19153
1) No, raising an exception doesn't always cause the program to terminate. Uncaught exceptions cause a program to terminate. You can surround code with a try/except
block, as follows, to stop the exception from propagating up the stack.
try:
file = open("foo.txt")
except IOError:
file = None
2) The code that actually catches the exception has access to the originating stack frame of the exception, and can decide what to do with it.
Re-raise error with original traceback:
try:
some_function()
except IOError as e:
raise
Re-raise error with new traceback (almost never as useful as the first case):
try:
some_function()
except IOError as e:
raise e
Don't re-raise, and print the exception and traceback:
try:
some_function()
except IOError as e:
import traceback
traceback.print_exc()
Upvotes: 0