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
> 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
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
> 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