Python程序在处理异常时终止
我在编辑这个问题,让它更清楚。
我在一个模块里创建了一个类,这个类导入了MySQLdb库。我发现如果用户传给我的类的表不存在,MySQLdb会抛出一个异常。我捕获了这个异常,并给客户端传递了一个新的异常。但是即使客户端捕获了我的异常,程序还是会终止。我也试过把MySQLdb给我的类的那个异常直接传给客户端。
因为客户端会在一个循环中调用我的方法,传入不同的表名,我不想程序因为表名错误而崩溃。我希望客户端能继续处理下一个有效的表名。这里有一段代码(tableName是传给方法的参数):
在我的类/模块中:
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()是一个在自己模块中定义的类的一部分,客户端正在导入这个模块。
谢谢。
5 个回答
补充一下其他回答的内容:如果程序遇到没有处理的错误(也就是未捕获的异常),程序会停止运行,但在停止之前,会先执行相关的 finally
块(如果有的话)和任何 atexit
处理器。所以理论上来说,在遇到未捕获的异常后,程序可以无限期地继续执行。
不过,没有哪类异常是天生就只会打印错误信息然后继续执行的。如果你想要这样的效果,可以使用 警告。
看了你修改过的问题,我不太确定你遇到的是哪两种问题。
如果你的问题只是想让异常只终止一次循环,而不是整个循环,那只需要简单地调整一下代码结构。不要这样写:
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
再次强调,这将始终无法捕获你抛出的异常,程序会因为追踪错误而退出。