Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

relative imports with the __import__ function

1 view
Skip to first unread message

Chris Colbert

unread,
Dec 8, 2009, 10:10:45 AM12/8/09
to pytho...@python.org
I have package tree that looks like this:

main.py
package
----__init__.py
----configuration.ini
----server
--------__init__.py
--------xmlrpc_server.py
--------controller.py
--------reco
------------<irrelevant.py's>
----segmentation
--------__init__.py
--------red_objects.py
----<other irrelevant folders>


main.py launches an instance of xmlrpc_server.py which, in turn,
imports controller.py.
controller.py reads configuration.ini to determine which
module/function to import from the segmentation directory and
subsequently use.

that config file specifies the module as 'red_objects' and the
function as 'segment_red'.

I am trying to dynamically import that module and func using the
__import__ statement but keep getting empty module errors.

In the following code segment, the failing code is uncommented, but
the commented code works fine:

seg_mod = 'red_objects'
smod = __import__('..segmentation.%s' % seg_mod, fromlist=[seg_func], level=-1)

#from ..segmentation import red_objects
#smod = red_objects

I have tried all sorts of values for the 'level' kwarg as well as
everywhich variation of the dotted relative notation.

I'm assuming i'm missing something fundamental on the import resolution...

As an aside, I would like to move main.py inside of the package
directory, but I dont know if that is possible with what i'm trying to
do here.

Thanks for any help.

Cheers!

Chris

Peter Otten

unread,
Dec 8, 2009, 11:48:02 AM12/8/09
to
Chris Colbert wrote:

> I'm assuming i'm missing something fundamental on the import resolution...

After some experimentation it turns out you have to provide some context for
__import__() to determine the absolute location of the requested module. The
required bit of information is the current module's __name__ attribute which
you can provide via the globals parameter:

def import_segmentation(name):
return getattr(__import__("segmentation." + name, level=2,
globals=globals()), name)

Peter

Chris Colbert

unread,
Dec 9, 2009, 8:18:10 AM12/9/09
to pytho...@python.org
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Many thanks Peter!
Almost like a charm!

It seems the relative import level is dependent on the location of the
main entry module. I thought the whole idea of relative imports was to
make the import independent of the entry point?

here is the import function i'm using

def import_segmentation(self):
# get the segmentation function defined in configuration.ini
parent_dir = os.path.split(os.path.dirname(__file__))[0]
prsr = ConfigParser.ConfigParser()
prsr.read(os.path.join(parent_dir, 'configuration.ini'))
seg_mod = prsr.get('segmentation', 'module')
seg_func = prsr.get('segmentation', 'function')
print __name__
smod = __import__('segmentation.%s' % seg_mod, globals=globals(),
fromlist=[seg_func], level=2)
sfunc = getattr(smod, seg_func)
return sfunc

for that import level of 2 to work the tree must look like this:

main.py
package
----__init__.py
----configuration.ini
----server
--------__init__.py
--------xmlrpc_server.py
--------controller.py
--------reco
------------<irrelevant.py's>
----segmentation
--------__init__.py
--------red_objects.py
----<other irrelevant folders>

but if I rearrange the package structure like this (just moving the
location of main.py):

package
----main.py


----__init__.py
----configuration.ini
----server
--------__init__.py
--------xmlrpc_server.py
--------controller.py
--------reco
------------<irrelevant.py's>
----segmentation
--------__init__.py
--------red_objects.py
----<other irrelevant folders>

I have to change the import to level=1 or I get this error:
ValueError: Attempted relative import beyond toplevel package

I don't understand why the location of my main.py should have ANY
bearing on relative import resolution.

But again, i'm probably just being dense and need someone to explain
it to me in newb speak ;)

Cheers,

Chris

Peter Otten

unread,
Dec 10, 2009, 5:24:04 AM12/10/09
to
Chris Colbert wrote:

> It seems the relative import level is dependent on the location of the
> main entry module. I thought the whole idea of relative imports was to
> make the import independent of the entry point?

You don't have to specify it explicitly, so you can move a module containing

from .foo import bar

into another package without changing its source code (provided there is a
foo submodule with a bar attribute). This includes the trivial case of
renaming the parent package.

Of course Python has to know the importing module's location, just like you
cannot meet me one block north and three blocks west unless you know where I
currently am.

See also

http://www.python.org/dev/peps/pep-0328/#rationale-for-relative-imports

Peter

0 new messages