relative imports with the __import__ function

Chris Colbert sccolbert at gmail.com
Wed Dec 9 08:18:10 EST 2009


On Tue, Dec 8, 2009 at 5:48 PM, Peter Otten <__peter__ at web.de> wrote:
> Chris Colbert wrote:
>
>> 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.
>
>
>> 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
> --
> 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



More information about the Python-list mailing list