I have the following code:
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)
file2.py
def tfun():
from file1 import TestException
raise TestException()
and the output from python file1.py
is the following:
I am running
I am running
I am caught
<class 'file1.TestException'>
I am generally caught
<class 'file1.TestException'>
First of all why the code gets executed twice in this case? I can understand that the import is recursive but why the code of the script get executed again?
Secondly, the second time it is not getting caught by the same except
block even though it is the same type as the first time, which also I cannot find an explanation for.
Finally, I am trying to find a workaround for this problem without moving anything to a new file but I it does not seem to be any. Is it possible to get over this problem?
Edit
For the second question I realized it is because the code is inside the module level.
If you run a module as a script (i.e. give its name to the interpreter, rather than importing it), it’s loaded under the module name
__main__
.If you then import the same module from your program, it’s reloaded and reexecuted under its real name. If you’re not careful, you may end up doing things twice.
http://effbot.org/zone/import-confusion.htm
Your are loading file1.py
twice, as two distinct modules. The first time it is loaded as a reesult of your command line:
python file1.py
In that case, file1.py is being loaded as the main module, __main__
.
The second time you are loading it as a result of your import statement:
from file1 import TestException
In that case, file1.py is being loaded as the module file1
.
Because file1.py is being loaded as two distinct modules, there are two distinct copies of everything in it. Particularly __main__.TestException
is different from file1.TestException
.
So, inside __main__
, the line:
except TestException as e:
is catching __main__.TestException
even as tfun()
is raising __file1__.TestException
. Inside file1
, that same line is catching file1.TestException
.
In the former case, the types do not match and the except:
clause is not run; in the latter case the type does match and the except:
clause is run.
Perhaps this program can make it more clear what is happening:
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__
Result:
$ 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__
A simple workaround is to modify file2.py:
def tfun():
from __main__ import TestException
raise TestException()
Result:
$ 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__
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With