string interpolation with both local and module variables?
Alex Martelli
aleaxit at yahoo.com
Wed May 2 07:50:06 EDT 2001
"Graham Guttocks" <graham_guttocks at yahoo.co.nz> wrote in message
news:mailman.988762323.7975.python-list at python.org...
> Greetings,
>
> I'm trying to do string interpolation on a textfile containing
> references to variables both in the local function, and also in one of
> my modules.
>
> As demonstrated below, this doesn't seem to work because variables in
> the calling function aren't available to the function doing the
> interpolation. Any ideas?
>
> def printmsg():
> foo = 'FOO'
> message = makemessage('/tmp/test.txt')
>
> def makemessage(file):
> fp = open(file)
> template = fp.read()
> from Defs import *
> text = template % vars()
> return text
>
> /tmp/test.txt contains:
>
> Hello %(USERNAME)s, how do you %(foo)s?
Just change the second line of printmsg() to:
message = makemessage('/tmp/test.txt', vars())
and makemessage() itself to, for example:
def makemessage(file, vardict):
fp = open(file)
template = fp.read()
import Defs
localdict = Defs.__dict__.copy()
localdict.update(vardict)
text = template % localdict
return text
One _might_ try to workaround the need for the
caller to pass his vars(), but that would require
a lot of work and black magic -- just passing
it seems much simpler.
In makemessage, I have here assumed that variables
in the passed vardict have precedence over those
coming from module Defs; it's easy to make it the
other way around, of course, just switch two lines:
localdict = vardict.copy()
localdict.update(Defs.__dict__)
The general idea of having the caller pass the
dictionary in which variables are to be looked
up by preference [normally its vars()] seems
sound, but of course there are many alternative
implementations that may have advantages. For
example, say that you want variable lookup for
each name XXX to occur this way:
-- if present in the caller's vars(), use that
-- else, if present in Defs, use that
-- else, make believe the variable exists AND
refers to a string of the form
"***variable XXX undefined***"
to allow a different style for debugging
template-files rather than try/except in
the sources.
OK, that's easy, too:
class ChainDicts:
def __init__(self, *dicts):
self.dicts = dicts
def __getitem__(self, name):
for dict in dicts:
try: return dict[name]
except KeyError: pass
return "***var %s undefined***" % name
and then:
def makemessage(file, vardict):
import Defs
dict = ChainDicts(vardict, Defs.__dict__)
fp = open(file)
template = fp.read()
text = template % dict
return text
Alex
More information about the Python-list
mailing list