I have previously built a shar-like Python utility, which reads (marked) imported modules, gzips and base64 encodes them, then generates a python script, which is fully standalone.
The included module source is placed into sys.modules at runtime, making imports possible without actually having the module files installed. A very nice thing for administrative scripts that have to work in unconfigured environments.
At that time I discovered a lot of information about how modules in Python work.
Reading the very interesting recipe at http://code.activestate.com/recipes/577887-a-simple-namespace-class/ made me realize, that modules are actually very useful as generic namespaces too.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def namespace():
'''Create an empty module to be used as generic namespace.
>>> ns = namespace()
>>> dir(ns)
[]
>>> ns.member = 'value'
>>> ns.member
'value'
'''
import imp
ns = imp.new_module('')
for attr in dir(ns):
delattr(ns, attr)
return ns
|
Let us examine, how these namespaces work
First we define a dumper:
>>> def whats_new_in(baltimore):
... print("{0}{3:^{1}} {4:<{2}s}: ]{5!s}[".format(
... '!', 9, 15, ':DBG:', 'namespace', vars(baltimore)))
Let's get a minimal module:
>>> import imp as namespace_from
>>> namespace = namespace_from.new_module('')
We can see, that there is some stuff there, which we did not really want:
>>> whats_new_in(namespace)
! :DBG: namespace : ]{'__name__': '', '__doc__': None, '__package__': None}[
But, alas, we can get rid of those ...
>>> for attr in dir(namespace):
... delattr(namespace, attr)
... as you can see:
>>> whats_new_in(namespace)
! :DBG: namespace : ]{}[
Let's use the namespace a little:
>>> namespace.to = 'be'
There you go!
>>> whats_new_in(namespace)
! :DBG: namespace : ]{'to': 'be'}[
Since this is not a dict ...
>>> try:
... namespace['dict_access'] = 78
... except TypeError:
... pass
... you cannot put stuff in there with key access:
>>> whats_new_in(namespace)
! :DBG: namespace : ]{'to': 'be'}[
But with vars
...
>>> vars(namespace)['that is'] = 'the question'
... this is actually possible:
>>> whats_new_in(namespace)
! :DBG: namespace : ]{'to': 'be', 'that is': 'the question'}[
Fake Import
Nesting module-based namespaces ...
>>> to = namespace
>>> to.be = to
>>> to.be.or_not = to.be
... makes them seem to be imported :)
>>> print(to.to)
be
>>> print(to.be.to)
be
>>> print(to.be.or_not.to)
be
Once we have anticipated the import ...
>>> sys.modules['to'] = to.be.or_not
>>> sys.modules['to.be'] = to.be
>>> sys.modules['to.be.or_not'] = to
... we can actually import stuff:
>>> from to.be.or_not import to
... REALLY!
>>> print(to)
be
Although, I may have confused Python a little bit or maybe just the reader ...
>>> whats_new_in(namespace)
! :DBG: namespace : ]{'to': 'be', 'that is': 'the question', 'or_not': <module '?' (built-in)>, 'be': <module '?' (built-in)>}[
I guess, that really seems to be a question ;-)
Decorator
Well, I don't know how decorators work, but if you promise not to tell anyone, I can give you this:
>>> NDA = (lambda: [( N,[DA (N,dA) for dA in dir(N)])
... for N, DA in ((namespace_from.new_module(''), delattr),)][0][0])
So, here comes obviously a namespace:
>>> ectory = NDA()
>>> ectory
<module '?' (built-in)>
But is it empty?
>>> dir(ectory)
[]
Are there really no members?
>>> ectomy = NDA()
>>> vars(ectomy)
{}
OK. I cannot resist ;-)
>>> class action:
... vas = ectomy
... vas . ectomy = {'really': 'hurts'}
>>> does = action()
>>> does.vas.ectomy['really'] == 'hurt'[ :-1 ]
False
>>> does.vas.ectomy['really'][ :-1 ] == 'hurt'
True
Have I offended someone?