Bill Jackson wrote: > Once again, I am having issues with imports... > > Until now, I thought the general guidelines were to rarely use 'from x > import y' syntax, except when you really want to copy names over.
No, the guideline is to not use "from x import *" except at the interactive prompt and occasionally in __init__.py's to "copy names over" as you put it. > However, I have run into issues by following this guideline. So... > > 1) What is going wrong in the example below? > 2) What is a good way to handle imports for packages w/subdirectories? > > Here is a sample directory structure: > > importtest/ > __init__.py > test2/ > __init__.py > someclass.py > mytest.py > > > Here are the definitions of the files: > > # importtest/__init__.py > from test2 import * > > # importtest/test2/__init__.py > from someclass import * > from test2 import * > > # importtest/test2/someclass.py > class SomeClass: > pass > > # importtest/test2/mytest.py > import importtest > print importtest.SomeClass > > > On import I get the following: > > >>> import importtest > Traceback (most recent call last): > File "<stdin>", line 1, in ? > File "/home/user/lib/python/importtest/__init__.py", line 1, in ? > from test2 import * > File "/home/user/lib/python/importtest/test2/__init__.py", line 2, in ? > from mytest import * > File "/home/user/lib/python/importtest/test2/mytest.py", line 3, in ? > print importtest.SomeClass > AttributeError: 'module' object has no attribute 'SomeClass' > >>> > > > The problem seems to be an 'order' issue. importtest/test2/__init__.py > has loaded someclass.py, but it doesn't seem to have copied its contents > into importtest/__init__.py....perhaps it is because it hasn't finished > all of its imports. Is this correct? You are right that it is an order issue. The line "from test2 import *" hasn't finished executing by the time "print importtest.SomeClass" is executed because the former is trying to execute the latter. > So what is a good way to deal with this? In files which contain > implementations, I thought it was best not to use 'from x import y', but > this seems to be the only way to get this to work: My recommendation is that inside packages, be as specific as is feasible with your imports, even if you expose the symbols at a higher level for external callers. If you have a module whose contents are being exposed in your __init__.py, never rely on the contents of that __init__.py in that code. Instead, go straight to the real modules that implement the symbols that you need. So mytest.py should read: from importtest.test2.someclass import SomeClass print SomeClass or from importtest.test2 import someclass print someclass.SomeClass -- Robert Kern "I have come to believe that the whole world is an enigma, a harmless enigma that is made terrible by our own mad attempt to interpret it as though it had an underlying truth." -- Umberto Eco -- http://mail.python.org/mailman/listinfo/python-list