Module imports during object instantiation

Bruno Desthuilliers bruno.42.desthuilliers at wtf.websiteburo.oops.com
Tue Aug 14 10:58:53 CEST 2007


Ritesh Raj Sarraf a écrit :
> Steve Holden wrote:

(snip)

>> What's leading you to conclude the import isn't being executed? You
>> realise, I trust, that the module's code will only be executed on the
>> first call to __init__()?
>>
> 
> Well. Putting it in a "try" inside __init__() doesn't do anything.

This would be highly suprising.

> The
> import never happens.

As soon as your running this code on a platform where os.name yields 
either 'nt' or 'dos', the import statement is executed. You can bet your 
ass on this. Now this import can fail for a lot of reasons (imported 
module not in sys.path, error in the imported module, etc), and since 
your catching *and dismissing* the ImportError, you don't know what 
*effectively* happens. It's like someone send you mails, you set your 
filter to trash mails from this person, and then complain this person 
never send you mails !-)

> And thus if I make a call in any of the methods, it
> fails with an error message. A NameError IIRC.

"IIRC" ? Inspecting the traceback may help, you know.

Anyway, there's a simple way to know what happens:

class Log:
     def __init__(self, verbose, lock = None):

         self.VERBOSE = bool(verbose)

         self.lock = bool(lock)
         if self.lock:
             self.dispLock = threading.Lock()
         else:
             self.dispLock = None

         if os.name == 'posix':
            self.platform = 'posix'
            self.color = get_colors()

         elif os.name in ['nt', 'dos']:
             self.platform = 'microsoft'

             try:
                 import SomeModule
             except ImportError, e:
                 # comment out next line before going to prod...
                 print >> sys.stderr, e
                 self.color = None
	    else:
                 self.color = SomeModule.get_colors_windows()

         else:
             self.platform = None
             self.color = None


This should print the exact ImportError message. Which may help. IMHO.


>> You are right in assuming that __init__() is called once per instance
>> created, and it's legitimate to make an import conditional in the way
>> you have because of the "execute code only once" behavior - if the
>> module is already in sys.modules then it won't be re-imported, the
>> existing one will be used.
>>
> 
> This is what even my understanding is. But am afraid to say that this
> understanding is not implemented in Python. 

Do you *really* believe that no one would have noticed if something as 
important as the import mechanism was broken ?

(snip)
> Now I have some questions.
> 
> Going with your point of try/except imports at the top level, I am having
> multiple imports at the top level for the multiple classes that I have in
> the module. Not everything from the top level imports is required for the
> class Log (Say, just one module is what is required).
> So when I do a `from module import Log`, do all the modules at the  top
> level get imported?

Yes.

> My understanding says Yes, and if that's true, that's
> bad IMO. 

No, that's the right thing to do. When a module is loaded, all the 
top-level code is executed. period. How else would the class  and def 
statements be executed ?

FWIW, modules are supposed to have high cohesion. If you put unrelated 
things in a same module, then it's *your* design that's bad.

> My ultimate goal is to make all my classes as independent as possible while
> keeping them as lightweight as possible. If all top level module import
> statements are getting executed during a `from module import class`, this
> is _not_ lightweight IMO.

Since a module is only imported once, this should not be such a concern. 
It's obviously much more "lightweight" than going thru the import each 
time you instanciate the class, just to find out that the module is 
already imported.

But anyway, if two classes should be "totally" independant from each 
other, then what on earth are they doing in the same module ?

> That's what led me to try imports in __init__() but unfortunately I haven't
> seen that working for me even once.

"not working" is not a very useful description of a problem. The import 
mechanism works and it works fine. Your problem is elsewhere, but you 
didn't provide enough information for us to help you.



More information about the Python-list mailing list