如果您将一个模块作为脚本运行(即将其名称提供给解释器,而不是导入它),则它将在模块名称
__main__
下加载。
如果您随后从程序中导入相同的模块,则会重新加载并在其真实名称下重新执行。 如果您不小心,可能会重复执行某些操作。
http://effbot.org/zone/import-confusion.htm
您正在以两个不同的模块加载
file1.py
,第一次是通过命令行加载的。
python file1.py
在这种情况下,file1.py被加载为主模块
__main__
。
第二次加载是由于您的导入语句引起的。
from file1 import TestException
在这种情况下,file1.py作为模块
file1
被加载。
因为file1.py作为两个不同的模块被加载,所以其中的每个东西都有两个不同的副本。特别是
__main__.TestException
与
file1.TestException
不同。
因此,在
__main__
内部,该行代码:
except TestException as e:
即使在 tfun()
抛出 __file1__.TestException
的情况下,仍然捕获了 __main__.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__
结果:
$ 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__
一个简单的解决方法是修改file2.py:
def tfun():
from __main__ import TestException
raise TestException()
结果:
$ 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__