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