为什么我能捕获由eval代码引发的SyntaxError(或IndentationError或TabError),但无法捕获源代码本身引起的错误?

22 投票
2 回答
2144 浏览
提问于 2025-04-15 16:44

考虑这两个代码片段:

try:
    a+a=a
except SyntaxError:
    print "first exception caught"

.

try:
    eval("a+a=a")
except SyntaxError:
    print "second exception caught"

在第二种情况下,“第二个异常...”的语句被打印出来了(异常被捕获),而在第一种情况下则没有。

第一个异常(我们称它为“语法错误1”)和第二个异常(“语法错误2”)有什么不同吗?

有没有办法捕获语法错误1(从而抑制编译时的错误)?把大块代码放在eval里并不是个好办法;)

2 个回答

5

简短回答:不可以。

语法错误是在代码被解析的时候发生的,对于普通的Python代码来说,这个解析是在代码执行之前进行的——也就是说,代码并没有在try/except块里面执行,因为根本就没有执行。

不过,如果你使用eval或者exec来运行一些代码,那么这个代码是在运行时被解析的,这样你就可以捕捉到异常了。

26

在第一种情况下,异常是由编译器引发的,而编译器是在 try/except 结构还不存在的时候就已经在运行了(因为编译器会在解析代码后立即设置这个结构)。在第二种情况下,编译器运行了两次——异常是在编译器作为 eval 的一部分运行时引发的,这时 try/except 结构已经在第一次编译器运行后设置好了。

所以,要捕捉语法错误,无论如何,你必须让编译器运行两次——eval 是一种方法,显式调用 compile 内置函数是另一种方法,import 也很方便(在把代码写到另一个文件后),execexecfile 也是其他可能的选择。但无论你用什么方法,语法错误只能在编译器第一次运行后,设置好你需要的 try/except 块之后才能被捕捉到!

撰写回答