Hooking exceptions outside of call stack

Warren Stringer warren at muse.com
Sun Jun 10 17:40:08 EDT 2007


Hey Josiah,

I just spent a couple hours with your example, and it explains a lot. Some
of your interactive session got garbled, so am reposting your
merged_namespace example, with tweaks:

#---------------------------------------------------------
def merged_namespace(*ns):
   try:
       __builtins__
       namespaces = ns + (globals(),__builtins__.__dict__)
   except NameError:
       namespaces = ns + (globals(),__builtin__)
   ns = {}
   for i in reversed(namespaces):
       ns.update(i)
   return ns

def foo():
   print type(globals())
   print a.b[c] #works!
   return 
#------------------------------------------
# was having trouble with embedded classes
# so, I tried this to track down the problem

class a(object):
    def __init__(self): print 'init a'
    class b(object):
        def __init__(self): print 'init b'
        class c(object):
            def __init__(self): print 'init c'
            pass

aa = a() # only prints 'init a', oops

# so, starting with this:

class A(dict):
    def __getattr__(self, name):
        # here's where a namespace resolver might go
        return self[name]
    
    def __getitem__(self,key):
        return key # useless, but simple
        
a = A()                  # build from scratch
a.__dict__['b'] = A()
a.b.__dict__['c'] = A()
print a.b[a.b.c] # works as expected
#print a.b[c] # NameError: name 'c' is not defined

#-------------------------
# back to Josiah's example 

ns = merged_namespace(a.b.__dict__)  
foo2 = type(foo)(foo.func_code, ns, foo.func_name, foo.func_defaults,
foo.func_closure)  
foo2() 
#---------------------------------------------------------

As I was tracing through merged_namespace, I noticed how large resulting
dict is. Too, bad there isn't an equivalent namespace resolution order, as
the there is for methods (or, is there? Am not sure where/how locals are
managed). Then a tupple could be passed to `foo2 = type(foo)(foo.func_code,
namespace, ...)` 

With a mro-style namespace, __getattr__ might be able to change namespaces,
on the fly. Too much of a performance hit? Could be. Fortunately, your
example precludes the performance question. Thanks

"Restartable exceptions", as Jean-Paul Calderone called it, might have
yielded results. But searching on his specific phrase yielded a long
discussion (http://www.python.org/search/hypermail/python-1994q2/0425.html)
that illuminates the implausibility of this approach in Python.

So, am replacing `a.b[c]` with `f(a.b,'c')`. The user still can type
"a.b[c]" but, no longer at the python prompt. Oh well.

Thanks again,

\~/ 




More information about the Python-list mailing list