catching my own exception

Peter Otten __peter__ at web.de
Sun Jun 20 04:53:08 EDT 2010


Nikola Skoric wrote:

> Dana Fri, 18 Jun 2010 20:01:45 +0200,
> Peter Otten <__peter__ at web.de> kaze:
>> Solution: move your startup code into a separate file and have it import
>> the village module.
> 
> Excellent, thanks! Everything works now, but I still don't quite get what
> the problem is...
> 
>> You are importing your main script elswhere. Your code then
>> effectively becomes
>>
>> try:
>>     # in another module
>>     raise village.SomethingBuiltError
>> except __main__.SomethingBeingBuiltError:
>>    print "caught"
>>
>> i. e. you get two versions of every class that are built from the same
>> code but not (recognized as) identical.
> 
> What I don't get is: what do you mean I'm importing my main script
> elsewhere by runing "python village.py"? SomethingBuiltError is
> defined in the same script that I'm runing, I didn't import it, did I?
> If you could please clear it up for me... or point me to relevant
> literature, that's also cool, I couldn't find this thing explained
> anywhere.

In Python, if you write

class A:
    pass

that is executable code just like an if-statement or a for-loop rather than 
a declaration, and this code creates a new class every time it is run. 
That's why

>>> items = []
>>> for i in range(5):
...     class A: pass
...     items.append(A)
...
>>> issubclass(A, A)
True
>>> issubclass(items[0], items[1])
False

creates 5 distinct classes. The same would go for modules if it weren't for 
the sys.modules cache:

>>> open("tmp.py", "w").write("print 'importing', __name__\n")
>>> import tmp
importing tmp
>>> import tmp # module is looked up in cache, code not run

If we clear the cache manually, the code in the module will be executed 
again:

>>> import sys
>>> del sys.modules["tmp"]
>>> import tmp
importing tmp

Now in your case village.py is first run as the main script and then 
imported from within account.py -- but the main script is put into the cache 
under the key "__main__" regardless of its actual name. Using our simple 
example:

$ python -i tmp.py
importing __main__
>>> import tmp
importing tmp

So you end up with a __main__ module and a village module that contain 
functions and classes built from the same code but with distinct identities.

In the account module you indirectly raise village.ExceptionWithLongName and 
in __main__ you try to catch __main__.ExceptionWithLongName.

Peter



More information about the Python-list mailing list