multiple namespaces within a single module?

J

jkn

Hello there

is it possible to have multiple namespaces within a single python
module?

I have a small app which is in three or four .py files. For various
reasons I would like to (perhaps optionally) combine these into one
file. I was hoping that there might be a simple mechanism that would
let me do this and maintain the namespaces referred to: so that the
'combined' file would look something like

#
# not real python
#

# originally from a.py
with namespace a:
def function():
pass

# ...

# originally from b.py
with namespace b:
def function():
pass

# originally from main module

a.function()
b.function()

etc.

Is there anything like this available?

Thanks
J^n
 
P

Peter Otten

jkn said:
is it possible to have multiple namespaces within a single python
module?

Unless you are abusing classes I don't think so.
I have a small app which is in three or four .py files. For various
reasons I would like to (perhaps optionally) combine these into one
file.

Rename your main script into __main__.py, put it into a zip file together
with the other modules and run that.
 
E

Ethan Furman

Peter said:
Unless you are abusing classes I don't think so.


Speaking of...

<code>
class NameSpace(object):
def __init__(self, globals):
self.globals = globals
self.current_keys = list(globals.keys())
def __enter__(self):
return self
def __exit__(self, *args):
new_items = []
for key, value in self.globals.items():
if key not in self.current_keys and value is not self:
new_items.append((key, value))
for key, value in new_items:
setattr(self, key, value)
del self.globals[key]

if __name__ == '__main__':
with NameSpace(globals()) as a:
def function():
print('inside a!')
with NameSpace(globals()) as b:
def function():
print('inside b!')

a.function()
b.function()
print(vars())
</code>

The NameSpace objects do *not* get their own copy of globals(), but for
functions, etc., it should work fine. As a bonus the above code works
for both 2.x and 3.x.

~Ethan~
 
P

Peter Otten

Ethan said:
Peter said:
Unless you are abusing classes I don't think so.


Speaking of...

<code>
class NameSpace(object):
def __init__(self, globals):
self.globals = globals
self.current_keys = list(globals.keys())
def __enter__(self):
return self
def __exit__(self, *args):
new_items = []
for key, value in self.globals.items():
if key not in self.current_keys and value is not self:
new_items.append((key, value))
for key, value in new_items:
setattr(self, key, value)
del self.globals[key]

if __name__ == '__main__':
with NameSpace(globals()) as a:
def function():
print('inside a!')
with NameSpace(globals()) as b:
def function():
print('inside b!')

a.function()
b.function()
print(vars())
</code>

The NameSpace objects do *not* get their own copy of globals(), but for
functions, etc., it should work fine. As a bonus the above code works
for both 2.x and 3.x.

Hm, what about

with NameSpace(globals()) as a:
x = "inside a!"
def function():
print(x)
with NameSpace(globals()) as b:
x = "inside b!"
def function():
print(x)

x = "inside main!"
a.function()
b.function()
 
E

Ethan Furman

Peter said:
Hm, what about

with NameSpace(globals()) as a:
x = "inside a!"
def function():
print(x)
with NameSpace(globals()) as b:
x = "inside b!"
def function():
print(x)

x = "inside main!"
a.function()
b.function()

It would have to be `a.x = ...` and `b.x = ...` with corresponding
`print(a.x)` and `print(b.x)`.

Hrm -- and functions/classes/etc would have to refer to each other that
way as well inside the namespace... not sure I'm in love with that...

~Ethan~
 
J

jkn

Hi Peter

Unless you are abusing classes I don't think so.


Rename your main script into __main__.py, put it into a zip file together
with the other modules and run that.

Hmm ... thanks for mentioning this feature, I didn't know of it
before. Sounds great, except that I gather it needs Python >2.5? I'm
stuck with v2.4 at the moment unfortunately...

J^n
 
E

Ethan Furman

Ethan said:
Hrm -- and functions/classes/etc would have to refer to each other that
way as well inside the namespace... not sure I'm in love with that...


Not sure I hate it, either. ;)

Slightly more sophisticated code:

<code>
class NameSpace(object):
def __init__(self, current_globals):
self.globals = current_globals
self.saved_globals = current_globals.copy()
def __enter__(self):
return self
def __exit__(self, *args):
new_items = []
for key, value in self.globals.items():
if (key not in self.saved_globals and value is not self
or key in self.saved_globals
and value != self.saved_globals[key]):
new_items.append((key, value))
for key, value in new_items:
setattr(self, key, value)
del self.globals[key]
self.globals.update(self.saved_globals)

if __name__ == '__main__':
x = 'inside main!'
with NameSpace(globals()) as a:
x = 'inside a?'
def fn1():
print(a.x)
with NameSpace(globals()) as b:
x = 'inside b?'
def fn1():
print(b.x)
def fn2():
print('hello!')
b.fn1()
y = 'still inside main'
a.fn1()
b.fn1()
print(x)
print(y)
</code>

~Ethan~
 
A

Arnaud Delobelle

Ethan said:
Hrm -- and functions/classes/etc would have to refer to each other that
way as well inside the namespace... not sure I'm in love with that...



Not sure I hate it, either.  ;)

Slightly more sophisticated code:

<code>
class NameSpace(object):
   def __init__(self, current_globals):
       self.globals = current_globals
       self.saved_globals = current_globals.copy()

   def __enter__(self):
       return self
   def __exit__(self, *args):
       new_items = []
       for key, value in self.globals.items():
           if (key not in self.saved_globals and value is not self
                   or key in self.saved_globals
                   and value != self.saved_globals[key]):

               new_items.append((key, value))
       for key, value in new_items:
           setattr(self, key, value)
           del self.globals[key]
       self.globals.update(self.saved_globals)

if __name__ == '__main__':
   x = 'inside main!'
   with NameSpace(globals()) as a:
       x = 'inside a?'
       def fn1():
           print(a.x)
   with NameSpace(globals()) as b:
       x = 'inside b?'
       def fn1():
           print(b.x)
       def fn2():
           print('hello!')
           b.fn1()
   y = 'still inside main'
   a.fn1()
   b.fn1()
   print(x)
   print(y)
</code>

Please! Metaclasses are the obvious way to proceed here :) Then there
is no need for the 'a.x' and 'b.x' cruft.

marigold:junk arno$ cat namespace.py
function = type(lambda:0)

def change_globals(f, g):
return function(f.__code__, g, f.__name__, f.__defaults__, f.__closure__)

class MetaNamespace(type):
def __new__(self, name, bases, attrs):
attrs['__builtins__'] = __builtins__
for name, value in attrs.items():
if isinstance(value, function):
attrs[name] = change_globals(value, attrs)
return type.__new__(self, name, bases, attrs)

class Namespace(metaclass=MetaNamespace):
pass


x = "inside main"

class a(Namespace):
x = "inside a"
def fn1():
print(x)

class b(Namespace):
x = "inside b"
def fn1():
print(x)
def fn2():
print("hello")
fn1()

y = "inside main"

a.fn1()
b.fn1()
b.fn2()
print(x)
print(y)
marigold:junk arno$ python3 namespace.py
inside a
inside b
hello
inside b
inside main
inside main

A bit more work would be needed to support nested functions and closures...
 
P

Peter Otten

jkn said:
Hi Peter



Hmm ... thanks for mentioning this feature, I didn't know of it
before. Sounds great, except that I gather it needs Python >2.5? I'm
stuck with v2.4 at the moment unfortunately...

You can import and run explicitly,

$ PYTHONPATH mylib.zip python -c'import mainmod; mainmod.main()'

assuming you have a module mainmod.py containing a function main() in
mylib.zip.
 
J

jkn

Hi Peter


[...]
You can import and run explicitly,

$ PYTHONPATH mylib.zip python -c'import mainmod; mainmod.main()'

assuming you have a module mainmod.py containing a function main() in
mylib.zip.

That looks very useful -thanks for the tip!

J^n
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top