Import aliases for moving a module?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sat Mar 28 02:17:31 EDT 2009


En Thu, 26 Mar 2009 15:23:50 -0300, zopyxfilter at googlemail.com
<zopyxfilter at googlemail.com> escribió:

> For a while a maintained a Python package  'foo' with a number of
> modules (including a nested structure of module). Now the package
> moved into a namespace package
> 'a.b.foo'. What is the way to approach making old code work with the
> new package in order
> that imports like
>
>  import foo.bar.xxx
>  or
>  from foo.bar import xxx
>
> remain working for existing code.

A quick and dirty solution is to have a foo package with an __init__.py
that imports *every* single name in the old package, from the new one, and
puts it in sys.modules under the old name.

C:\temp>tree /f a
C:\TEMP\A
│   __init__.py
│
└───b
      │   __init__.py
      │
      └───foo
              one.py
              three.py
              two.py
              __init__.py


C:\temp>tree /f foo
C:\TEMP\FOO
      __init__.py

C:\temp>type foo\__init__.py
import warnings
warnings.warn("The 'foo' package is obsolete; use 'a.b.foo' instead",
      DeprecationWarning, 2)

import sys
  from a.b import foo
  from a.b.foo import one, two
sys.modules['foo.one'] = one
sys.modules['foo.two'] = two

# very last line!
sys.modules['foo'] = foo
# now *this* module is gone

C:\temp>type a\b\foo\one.py
print "This is one.py", __file__, __name__

C:\temp>type a\b\foo\two.py
print "This is two.py", __file__, __name__

C:\temp>type a\b\foo\three.py
print "This is three.py", __file__, __name__

All other __init__.py files are empty. Now, you can import foo and its
contents under the old and new names:

py> import foo
__main__:1: DeprecationWarning: The 'foo' package is obsolete; use
'a.b.foo' ins
tead
This is one.py a\b\foo\one.pyc a.b.foo.one
This is two.py a\b\foo\two.pyc a.b.foo.two
py> import foo.one
py> import a.b.foo.one
py> a.b.foo.one
<module 'a.b.foo.one' from 'a\b\foo\one.pyc'>
py> foo.one
<module 'a.b.foo.one' from 'a\b\foo\one.pyc'>
py> foo.one is a.b.foo.one
True
py> import foo.two
py> import a.b.foo.two

Note that one.py and two.py are imported only once. *BUT* notice what
happens when you import three.py, that was NOT included in foo\__init__.py:

py> import foo.three
This is three.py a\b\foo\three.pyc foo.three
py> import a.b.foo.three
This is three.py a\b\foo\three.pyc a.b.foo.three

That module was imported *twice*. So it's important to pre-import (inside
foo\__init__.py) *every* name that was present in the old foo package. If
this is not feasible (there are many names, or loading all of them would
be too slow, or whatever) you may implement a "lazy" importer. See
__init__.py in the email package for an example.

-- 
Gabriel Genellina




More information about the Python-list mailing list