[Import-sig] imputil

Gordon McMillan gmcm@hypernet.com
Wed, 14 Mar 2001 23:16:19 -0500


Michel Sanner wrote:
> 
> I am trying to come up with a way to handle versions of packages
> using imputil. I got version 1.12 from the CVS server and I try
> the following:
> 
> package structure:
> 
> A/
>         __init__.py
>                 from imputil import ImportManager
>                 ImportManager().install()
>         A_1_0/
>                 __init__.py
>                 B.py
>         A_1_1/
>                 __init__.py
>                 B.py
>         A_1_2/
>                 __init__.py
>                 B.py
> 
> Here is what I'd like to achieve:
> >>> import A
> >>> # the __init__.py file of the A package identifies A_1_0,
> >>> # A_1_1 and A_1_2 as sub packages and installs a special
> >>> # importer which will import from A_VERSION every time that
> >>> # something from A should be imported

Maybe an important point: what exactly do you mean by 
"installs a special importer"?

> >>> A.importer.set_version("1_0")
> >>> from A import B # should import A.A_1_0.B
> >>>
> 
> The first problem I have is the following:
> 
> if I type:
> 
> Python 1.5.2 (#0, Apr 14 2000, 10:15:38) [C] on irix646
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>>
> import A >>> from A import A_1_0 Traceback (innermost last):
>   File "<stdin>", line 1, in ?
> ImportError: cannot import name A_1_0
> >>>

ImportManager doesn't do any importing. Something along the 
lines of 
 sys.path.append(A.importer) 
might do the trick.
 
> if I type "from A import A_1_0" BEFORE importing the package A it
> works fine
> 
> Python 1.5.2 (#0, Apr 14 2000, 10:15:38) [C] on irix646
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam >>>
> from A import A_1_0 >>> A_1_0 <module 'A.A_1_0' from
> 'A/A_1_0/__init__.pyc'> >>>
> 
> more generally, I do not understand how imputil should be used.
> It seems that I should sub-class Importer and overwrite the
> get_code method. How would I then make this importer the one used
> for my package ?

Actually, in this case you don't really *need* imputil. You have 
a normal package structure, and just want to indulge in a little 
indirection. Most people would probably (in A/__init__.py) do 
an import * on the proper version. If it's small enough (or it's all 
going to end up loaded anyway) this is OK.

To do things on demand, you've got a bunch of choices, many 
of them dirty, nasty tricks (such as assigning to 
sys.modules['A'] - 'nuff said about that <wink wink>). You 
could certainly use imputil (but you'll need to put an 
imputil.BuiltinImporter() on sys.path, too). But since you're 
only talking about subpackages, you can do more private 
things. Among the things that happen when someone imports 
A.B is that Python looks in  A for the name B, which is to say 
that it looks in A/__init__.py's module dictionary. So you don't 
really need to provide a whole importer, you just need to 
provide the name B (bound sooner or later to the module 
<version>/B.py). Another choice is to play with the packages 
__path__ attribute in __init__.py (but I'm not fond of that, 
either).

[I am *not* dissing imputil here at all; but imputil affects *all* 
imports once it's installed so you need to be careful of side 
effects.]

- Gordon