Hi!
This is in Python 2.3.4 under WinXP.
I have a situation where I think changing the behaviour of a namespace
would be very nice. The goal is to be able to run a python file from
another in a separate namespace in such a way that a NameError is not
raised if a non-existing variable is used in the file. The file that I
want to run is taken out of context, and some needed variables may be
missing that are normally there when used in the intended context. OK!
When I run it out of context, I do not want the execution to stop
half-way through the file based on NameErrors, instead a predefined
dummy variable should be used. The question is: Can I achieve that?
Google didn't give me much, so I experimented a bit: First, I created a
dummy object, which is meant to be used when a variable is missing:
class dummyClass(obje ct):
pass
dummyObject = dummyClass()
The actual dummy object is supposed to be a bit more complicated than
that. The next step was to subclass dict:
class forgivingDict(d ict):
def __init__(self,* args,**kwargs):
dict.__init__(s elf,*args,**kwa rgs)
def __getitem__(sel f,key):
print ' Getting', key
try:
return dict.__getitem_ _(self,key)
except KeyError:
return dummyObject
def __setitem__(sel f,key,value):
print ' Setting', key, 'to', value
dict.__setitem_ _(self,key,valu e)
def __contains__(se lf,item):
return True
def __repr__(self):
return 'forgivingDict( %s)' % (dict.__repr__( self),)
Then I tried to execute a file using a forgivingDict() as namespace:
ns = forgivingDict()
execfile(filePa th, ns)
A file containing the following passes perfectly OK:
a = 0
b = a
But a file containing the following produces a NameError:
b = a
The error traceback for the interested:
Traceback (most recent call last):
File "//charm/mikael/My
Documents/Programmering/Python/Tester/voidTest.py", line 130, in ?
execfile('test2 .py', ns)
File "test2.py", line 1, in ?
b = a
NameError: name 'a' is not defined
Now, that is exactly what is to expect if ns is a dict(), but I was
hoping that b would have ended up as dummyObject when ns is a
forgivingDict() . One thing: Nothing is printed out when execfile-ing the
files, which means that the methods forgivingDict._ _getitem__ and
forgivingDict._ _setitem__ are never used. My guess was that the
execution done by execfile uses dict.__getitem_ _(ns, key) and
dict.__setitem_ _(ns,key,value) instead of ns[key] and ns[key]=value when
getting and setting variables. That is probably intentional from the
developers and done that way for a good reason.
Alternative test: I've tried to replace __builtin__.dic t with my
forgivingDict, slightly modified to make sure that the inheritance still
works, which didn't change anything. So it seams that the execution done
by execfile does *not* use dict.__getitem_ _(ns, key) and
dict.__setitem_ _(ns,key,value) after all, but something else. Probably
the original dict is around somewhere else, and execfile uses the
corresponding methods of that.
My approach seems flawed. Any ideas? Can I somehow execute a complete
file even if there are non-existent variables used somewhere? A
try-except around the execfile statement is not an alternative, since
that stops the execution where the error occurs.
Should I perhaps read up on the compiler module? I mean: Using the
compiler module to analyze the content of the file, and based on that
updating my namespace before executing the file.
/MiO
This is in Python 2.3.4 under WinXP.
I have a situation where I think changing the behaviour of a namespace
would be very nice. The goal is to be able to run a python file from
another in a separate namespace in such a way that a NameError is not
raised if a non-existing variable is used in the file. The file that I
want to run is taken out of context, and some needed variables may be
missing that are normally there when used in the intended context. OK!
When I run it out of context, I do not want the execution to stop
half-way through the file based on NameErrors, instead a predefined
dummy variable should be used. The question is: Can I achieve that?
Google didn't give me much, so I experimented a bit: First, I created a
dummy object, which is meant to be used when a variable is missing:
class dummyClass(obje ct):
pass
dummyObject = dummyClass()
The actual dummy object is supposed to be a bit more complicated than
that. The next step was to subclass dict:
class forgivingDict(d ict):
def __init__(self,* args,**kwargs):
dict.__init__(s elf,*args,**kwa rgs)
def __getitem__(sel f,key):
print ' Getting', key
try:
return dict.__getitem_ _(self,key)
except KeyError:
return dummyObject
def __setitem__(sel f,key,value):
print ' Setting', key, 'to', value
dict.__setitem_ _(self,key,valu e)
def __contains__(se lf,item):
return True
def __repr__(self):
return 'forgivingDict( %s)' % (dict.__repr__( self),)
Then I tried to execute a file using a forgivingDict() as namespace:
ns = forgivingDict()
execfile(filePa th, ns)
A file containing the following passes perfectly OK:
a = 0
b = a
But a file containing the following produces a NameError:
b = a
The error traceback for the interested:
Traceback (most recent call last):
File "//charm/mikael/My
Documents/Programmering/Python/Tester/voidTest.py", line 130, in ?
execfile('test2 .py', ns)
File "test2.py", line 1, in ?
b = a
NameError: name 'a' is not defined
Now, that is exactly what is to expect if ns is a dict(), but I was
hoping that b would have ended up as dummyObject when ns is a
forgivingDict() . One thing: Nothing is printed out when execfile-ing the
files, which means that the methods forgivingDict._ _getitem__ and
forgivingDict._ _setitem__ are never used. My guess was that the
execution done by execfile uses dict.__getitem_ _(ns, key) and
dict.__setitem_ _(ns,key,value) instead of ns[key] and ns[key]=value when
getting and setting variables. That is probably intentional from the
developers and done that way for a good reason.
Alternative test: I've tried to replace __builtin__.dic t with my
forgivingDict, slightly modified to make sure that the inheritance still
works, which didn't change anything. So it seams that the execution done
by execfile does *not* use dict.__getitem_ _(ns, key) and
dict.__setitem_ _(ns,key,value) after all, but something else. Probably
the original dict is around somewhere else, and execfile uses the
corresponding methods of that.
My approach seems flawed. Any ideas? Can I somehow execute a complete
file even if there are non-existent variables used somewhere? A
try-except around the execfile statement is not an alternative, since
that stops the execution where the error occurs.
Should I perhaps read up on the compiler module? I mean: Using the
compiler module to analyze the content of the file, and based on that
updating my namespace before executing the file.
/MiO
Comment