[Tutor] Help with packages and namespaces please

Kent Johnson kent37 at tds.net
Sat Oct 13 15:19:27 CEST 2007


Andrew Wu wrote:

> Let's say I have these files in one directory:
> 
> PrintBase.py
> PrintHello.py
> PrintBye.py

> I'd like to reorganize the files so they're like the Sound example in 
> the Python tutorial:
> 
> PrintMe/
> PrintMe/PrintBase/PrintBase.py
> PrintMe/PrintHello/PrintHello.py
> PrintMe/PrintBye/PrintBye.py

Will there be more modules in each subdirectory? I'm not sure if this is 
just for learning or if it is a simplification of a real problem, but 
from your description of the classes it sounds like they belong in the 
same package.

> I've created empty __init__.py files in each of the subdirectories.  
> Here I run into a number of problems and get confused - my goal is to 
> keep the import statements as they are (the actual files I'd be editing 
> are many and I'd rather avoid having to edit them all) - is there 
> something I can put in the __init__.py files so that the modules are 
> brought into namespace w/o having to use absolute module notation?

You can bring names into the package namespace, but the actual code will 
still run in the module where it is defined. For example, in 
PrintMe/PrintBase/__init__.py you can say
   from PrintBase import Printbase

Hmm. I'm not sure if this will work the way you want because of the name 
collisions. Using the sound example where the names are unique, suppose 
wavread.py includes a function read_wav(). Then in Formats/__init__.py 
you can say
   from wavread import read_wav

This imports the name read_wav into the Formats package namespace so 
other code will be able to say
   from Sound.Formats import read_wav

In your example, *without* the import in PrintBase/__init__.py it is 
already valid to say
   from PrintMe.PrintBase import PrintBase
which will access the *module* PrintBase. When you add the line
   from PrintBase import Printbase
to __init__.py then there are two possible meanings for 
PrintMe.PrintBase.PrintBase and I don't know which one will have 
priority. My guess is that the module import will win but I don't know.

At best this seems like a recipe for endless confusion - you have three 
entities named PrintBase - a package, a module and a class.

If the import in __init__ promotes the class as you want, it still won't 
help with the imports in PrintHello.py - it will still have to say at least
   from PrintMe.PrintBase import PrintBase

Why do you want to do this? It looks like a confusing mess to me.
> 
> As simple tests, I've tried running different import commands in the 
> python interpreter:
> 
> I've tried adding the absolute directory paths to __path__ in each 
> __init__.py per subdirectory, and adding the paths to sys.path.  

Yuck. What is the point of the directories and packages if you are going 
to put every thing on sys.path anyway? But I think it should work if you 
put each of the subdirectories of PrintMe on sys.path.

> When I 
> do that and run the python intepreter and try 'from PrintMe.PrintHello 
> import PrintHello' I get an error saying 'Error when calling the 
> metaclass bases, module.__init__() takes at most 2 arguments (3 
> given)'.  The same code functioned fine when all the files were in the 
> same directory, so I'm confused about why the interpreter thinks I'm 
> passing 3 arguments along.

You get an error on the import? Please show the traceback.

Kent


More information about the Tutor mailing list