Python程序在处理异常时终止

0 投票
5 回答
2610 浏览
提问于 2025-04-17 16:48

我在编辑这个问题,让它更清楚。

我在一个模块里创建了一个类,这个类导入了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 个回答

1

补充一下其他回答的内容:如果程序遇到没有处理的错误(也就是未捕获的异常),程序会停止运行,但在停止之前,会先执行相关的 finally(如果有的话)和任何 atexit 处理器。所以理论上来说,在遇到未捕获的异常后,程序可以无限期地继续执行。

不过,没有哪类异常是天生就只会打印错误信息然后继续执行的。如果你想要这样的效果,可以使用 警告

1

异常并不总是会导致程序结束。根据文档

在执行过程中发现的错误称为异常,这些异常并不是一定会致命的:

如果在一个try: except块中抛出了异常,并且except部分指定了这个异常或它的父类,那么这个异常就会被处理。

处理异常时,你可以检查它,了解与之相关的所有信息。我之前从来没有使用过traceback模块,但看起来它包含了你需要的所有信息。

我想你第二个问题的答案取决于你希望用户看到什么。异常应该显示出来吗?(你可以访问回溯信息)。应该只显示消息吗?你应该记录回溯信息吗?

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

再次强调,这将始终无法捕获你抛出的异常,程序会因为追踪错误而退出。

撰写回答