Import into specified namespace

Fritz Bosch uthand at hotmail.com
Tue Sep 14 10:27:08 EDT 2004


aleaxit at yahoo.com (Alex Martelli) wrote:
> ...
> Why not sys.modules['sys'] = mydic instead of trying to rebind
> sys.__dict__?   You can't affect those other modules which have ALREADY
> imported sys, yourself included (but as for you, you can remedy that
> easily -- sys = sys.modules['sys'] = mydic...), but otherwise you should
> be OK.  sys.__dict__.update(mydic) as the last statement might also be
> an alternative (and if it works for your purposes, it's cleaner than
> rebinding sys.modules['sys']!-).

Thanks for the hint.  I actually want a different behavior for the
namespace, so the second suggestion (though cleaner) won't work for
me.  In fact, I had to modify the first to get what I want, namely a
namespace (for a module) with a reverse lookup capability, i.e. given
an object, it returns the object's name (if any) inside the namespace.

I eventually got following to run:

Assume a small module 'mymod.py', for which I need a namespace with
reverse lookup capability:
-------------------------------------------------------------
import sys

def fn():
    name = fn.__module__
    # print the id of this module in sys.modules, along with the ids
    #  of the function and current globals, and the module's dict
    print 'mymod name:%s id(sys.modules[name]):%s' % (
                name, id(sys.modules[name]))
    print '  id(fn.func_globals):%s id(globals()):%s \
id(sys.modules[name].__dict__):%s' % (
                id(fn.func_globals), id(globals()),
                id(sys.modules[name].__dict__))
-------------------------------------------------------------

To do this, I have defined following namespace.py module:
-------------------------------------------------------------
import sys
import os

class RNameSpace(dict):
    def __init__(self, *args, **kw):
        dict.__init__(self, *args, **kw)
        self.__rdict = {}
        for name, val in self.items():
            self.__rdict[id(val)] = name
    def __setitem__(self, name, val):
        if name in self:
            del self.__rdict[id(self[name])]
        dict.__setitem__(self, name, val)
        self.__rdict[id(val)] = name
    def update(self, other):
        for name, val in other.items():
            self[name] = val
    def __delitem__(self, name):
        if name in val:
            del self.__rdict[id(self[name])]
        dict.__delitem__(self, name)
    def rlookup(self, obj):
        return self.__rdict[id(obj)]

class Module(object):
    def __init__(self, mod_name, namespace=None):
        if namespace is None:
            namespace = RNameSpace()
        if isinstance(namespace, RNameSpace):
            self.__dict__ = namespace
        else:
            self.__dict__ = RNameSpace(namespace)
        module = __import__(mod_name)
        self.__dict__.update(module.__dict__)
    def reload(self):
        file = os.path.splitext(self.__file__)[0] + '.py'
        execfile(file, self.__dict__)
    def install(self):
        mod_name = self.__name__
        sys.modules[mod_name] = self

if __name__ == '__main__':
    ns = RNameSpace(a=1,b=2)
    c1 = 3
    ns['c']=c1
    a1 = ns['a']
    print ns.rlookup(a1), ns.rlookup(c1)
    
    print "create Module md from 'mymod' to use RNameSpace:"
    md = Module('mymod')
    print 'id(md):%s id(md.__dict__):%s' % (id(md), id(md.__dict__))

    print "\nnote that md.fn still uses original namespace:"
    md.fn()

    print '\nreload the file - now md.fn used the RNameSpace:'
    md.reload()
    md.fn()

    print '\nan import still uses the original namespace:'
    import mymod
    mymod.fn()

    print '\ninstall the module - subsequent imports \
use the altered namespace:'
    md.install()
    import mymod
    mymod.fn()
-------------------------------------------------------------

>From the above it can be seen that it was necessary to create a
module-like object with the specified namespace and to call execfile
with this namespace ? I could find no other way to make the
classes/functions inside mymod use the namespace.  Replacing the
sys.modules entry with this object then causes subsequent imports to
use the module-like object.

B.t.w. am I re-inventing the wheel here?  Is there another way to get
the name from given an object id?

Fritz



More information about the Python-list mailing list