为了清晰起见,我正在编辑这个问题。
我在导入MySQLdb的模块中创建了一个类。我发现如果用户传递给我的类的表不存在,MySQLdb将引发异常。我正在捕获该异常,并将新的异常传递给客户端。但即使客户端捕获了我的异常,该程序仍然会终止。我也试过向客户端传递同样的异常MySQLdb给我的班级。
由于客户端将在循环中调用我的方法,传入各种表名,我不希望程序在表名不好的情况下阻塞。我希望客户端的迭代继续下一个有效的表名。这是一个片段(tableName是方法的arg传递):
在我的课程/模块中:
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. ***")
在客户端:
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
我希望客户端在调用my_method(BadTableName)之后继续。
顺便说一下,my_method()是客户端导入的自己模块中定义的类的一部分。
谢谢。
答案 0 :(得分:1)
异常并不总是导致程序结束。来自docs:
执行期间检测到的错误称为异常,而不是 无条件致命:
如果在try:except块中引发异常并且except
子句指定异常或异常的超类,则将处理该异常。
处理异常时,您可以检查它并查找与其相关的所有信息。我之前从未使用过traceback
模块,但看起来它包含了您需要的所有内容。
我想你的第二个问题取决于你希望用户看到什么。是否应该显示例外情况? (您可以访问回溯)。应该只显示消息吗?你应该记录回溯吗?
答案 1 :(得分:1)
添加到其他答案:未捕获的异常将终止程序,但仅在执行适用的finally
block(如果有)和任何atexit
handlers之后。所以原则上,在未捕获的异常之后可以无限期地继续执行。
不存在任何类别的异常,只会打印错误消息并按性质继续执行。如果您需要,请使用warnings。
答案 2 :(得分:0)
1)不,引发异常并不总是导致程序终止。 未捕获异常导致程序终止。您可以使用try/except
块包围代码,如下所示,以阻止异常向上传播。
try:
file = open("foo.txt")
except IOError:
file = None
2)实际捕获异常的代码可以访问异常的原始堆栈帧,并可以决定如何处理它。
使用原始追溯重新引发错误:
try:
some_function()
except IOError as e:
raise
使用新的回溯重新引发错误(几乎从未像第一种情况那样有用):
try:
some_function()
except IOError as e:
raise e
不要重新加注,并打印异常和追溯:
try:
some_function()
except IOError as e:
import traceback
traceback.print_exc()
答案 3 :(得分:0)
未捕获的异常将终止程序。 捕获异常不会
如果捕获到异常,则可以使用traceback模块输出堆栈跟踪:
http://docs.python.org/2/library/traceback.html#traceback-examples
答案 4 :(得分:0)
阅读完编辑的问题后,我不确定你遇到了哪两个问题。
如果您的问题仅仅是您只想要一个异常来终止一个循环迭代而不是整个循环,那么只需要以明显的方式重新嵌套语句。而不是:
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
这样做:
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
另一方面,如果问题是客户端没有捕获异常,则问题很可能是您的MyException
不是Exception
的子类。至少有三种方法可以实现。
由于您使用的是旧式except
语法(except Exception, e:
)而不是新式(except Exception as e:
),因此您可能正在使用较旧的Python版本来提升类不从BaseException
继承的。例如:
class MyException(object):
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
根据您的Python版本,这可能无法引发MyException
而是引发TypeError('
Out[11]: TypeError('exceptions must be old-style classes or derived from BaseException, not MyException')
(将被捕获),或打印警告,或者只是按照您的要求默默“工作”它(意味着你没有抓到任何东西,你的程序退出了回溯)。
与此同时,即使在2.7中,你仍然可以提升旧式课程,这也不会被抓住:
class MyException:
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
这将始终无法捕获异常,您的应用将退出并带有回溯。
最后,如果您继承自BaseException
而不是Exception
,那么显然Exception
将无法抓住它。
class MyException(BaseException):
def __init__(self, msg):
pass
try:
raise MyException("dsfsdf")
except Exception:
pass
再一次,这总是无法捕捉到你所筹集的东西,你将退出追溯。