异常执行两次,它被另一个不同的块捕获

zbs*_*zbs 6 python import recursion exception

我有以下代码:

file1.py

from file2 import tfun

class TestException(Exception):
    pass

try:
    print 'I am running'
    tfun()
except TestException as e:
    print 'I am caught'
    print type(e)
except Exception as e:
    print 'I am generally caught'
    print type(e)
Run Code Online (Sandbox Code Playgroud)

file2.py

def tfun():
    from file1 import TestException
    raise TestException()
Run Code Online (Sandbox Code Playgroud)

输出来自python file1.py以下内容:

I am running
I am running
I am caught
<class 'file1.TestException'>
I am generally caught
<class 'file1.TestException'>
Run Code Online (Sandbox Code Playgroud)

首先,在这种情况下代码执行两次的原因是什么?我可以理解导入是递归的,但为什么脚本的代码再次执行?

其次,第二次它没有被同一个except块捕获,即使它与第一次类型相同,我也找不到解释.

最后,我试图找到解决此问题的方法,而不将任何内容移动到新文件,但我似乎没有任何.有可能克服这个问题吗?

编辑

对于第二个问题,我意识到这是因为代码在模块级别内.

Rob*_*obᵩ 7

如果您将模块作为脚本运行(即将其名称提供给解释器,而不是导入它),则将其加载到模块名称下__main__.

如果您从程序中导入相同的模块,则会以其真实名称重新加载并重新执行.如果你不小心,你最终可能会做两次事情.

http://effbot.org/zone/import-confusion.htm

您正在加载file1.py两次,作为两个不同的模块.第一次作为命令行的reesult加载:

python file1.py
Run Code Online (Sandbox Code Playgroud)

在这种情况下,正在加载file1.py作为主模块__main__.

第二次由于import语句而加载它:

from file1 import TestException
Run Code Online (Sandbox Code Playgroud)

在这种情况下,正在加载file1.py作为模块file1.

因为file1.py作为两个不同的模块加载,所以其中包含两个不同的副本.特别__main__.TestException是不同于file1.TestException.

所以,内线__main__,线:

except TestException as e:
Run Code Online (Sandbox Code Playgroud)

__main__.TestException即使tfun()是在提高,也在捕捉__file1__.TestException.在内部file1,同一条线正在捕捉file1.TestException.

在前一种情况下,类型不匹配,并且except:子句不运行; 在后一种情况下,类型匹配并except:运行子句.

也许这个程序可以更清楚地说明发生了什么:

from file2 import tfun

class TestException(Exception):
    pass

try:
    print 'I am calling file2.tfun from', __name__
    tfun()
    print 'I have called file2.tfun from', __name__
except TestException as e:
    print 'I am caught in %s'%(__name__)
    print type(e), TestException
except Exception as e:
    print 'I am generally caught in %s'%__name__
    print type(e), TestException
print 'I am exiting from',__name__
Run Code Online (Sandbox Code Playgroud)

结果:

$ python file1.py 
I am calling file2.tfun from __main__
I am calling file2.tfun from file1
I am caught in file1
<class 'file1.TestException'> <class 'file1.TestException'>
I am exiting from file1
I am generally caught in __main__
<class 'file1.TestException'> <class '__main__.TestException'>
I am exiting from __main__
Run Code Online (Sandbox Code Playgroud)

一个简单的解决方法是修改file2.py:

def tfun():
    from __main__ import TestException
    raise TestException()
Run Code Online (Sandbox Code Playgroud)

结果:

$ python file1.py 
I am calling file2.tfun from __main__
I am caught in __main__
<class '__main__.TestException'> <class '__main__.TestException'>
I am exiting from __main__
Run Code Online (Sandbox Code Playgroud)

  • +1我认为`__main __.TestException`和`file1.TestException`之间的区别是最棘手的部分. (2认同)