It can be useful in 'declarative python'. For instance, in the below FooDef
and BarDef
are classes used to define a series of data structures which are then used by some package as its input, or its configuration. This allows you a lot of flexibility in what your input is, and you don't need to write a parser.
# FooDef, BarDef are classes
Foo_one = FooDef("This one", opt1 = False, valence = 3 )
Foo_two = FooDef("The other one", valence = 6, parent = Foo_one )
namelist = []
for i in range(6):
namelist.append("nm%03d"%i)
Foo_other = FooDef("a third one", string_list = namelist )
Bar_thing = BarDef( (Foo_one, Foo_two), method = 'depth-first')
Note that this configuration file uses a loop to build up a list of names which are part of the configuration of Foo_other
. So, this configuration language comes with a very powerful 'preprocessor', with an available run-time library. In case you want to, say, find a complex log, or extract things from a zip file and base64 decode them, as part of generating your configuration (this approach is not recommended, of course, for cases where the input may be from an untrusted source...)
The package reads the configuration using something like the following:
conf_globals = {} # make a namespace
# Give the config file the classes it needs
conf_globals['FooDef']= mypkgconfig.FooDef # both of these are based ...
conf_globals['BarDef']= mypkgconfig.BarDef # ... on .DefBase
fname = "user.conf"
try:
exec open(fname) in conf_globals
except Exception:
...as needed...
# now find all the definitions in there
# (I'm assuming the names they are defined with are
# significant to interpreting the data; so they
# are stored under those keys here).
defs = {}
for nm,val in conf_globals.items():
if isinstance(val,mypkgconfig.DefBase):
defs[nm] = val
So, finally getting to the point, globals()
is useful, when using such a package, if you want to mint a series of definitions procedurally:
for idx in range(20):
varname = "Foo_%02d" % i
globals()[varname]= FooDef("one of several", id_code = i+1, scale_ratio = 2**i)
This is equivalent to writing out
Foo_00 = FooDef("one of several", id_code = 1, scale_ratio=1)
Foo_01 = FooDef("one of several", id_code = 2, scale_ratio=2)
Foo_02 = FooDef("one of several", id_code = 3, scale_ratio=4)
... 17 more ...
An example of a package which obtains its input by gathering a bunch of definitions from a python module is PLY (Python-lex-yacc) http://www.dabeaz.com/ply/ -- in that case the objects are mostly function objects, but metadata from the function objects (their names, docstrings, and order of definition) also form part of the input. It's not such a good example for use of globals()
. Also, it is imported by the 'configuration' - the latter being a normal python script -- rather than the other way around.
I've used 'declarative python' on a few projects I've worked on, and have had occasion to use globals()
when writing configurations for those. You could certainly argue that this was due to a weakness in the way the configuration 'language' was designed. Use of globals()
in this way doesn't produce very clear results; just results which might be easier to maintain than writing out a dozen nearly-identical statements.
You can also use it to give variables significance within the configuration file, according to their names:
# All variables above here starting with Foo_k_ are collected
# in Bar_klist
#
foo_k = [ v for k,v in globals().items() if k.startswith('Foo_k_')]
Bar_klist = BarDef( foo_k , method = "kset")
This method could be useful for any python module that defines a lot of tables and structures, to make it easier to add items to the data, without having to maintain the references as well.
globals
is perhaps a little misleading.globals()
is essentially thelocals()
of a module. The closest Python comes to globals that are truly global to all of your program is the__builtin__
module; anything you add to that module becomes available in all namespaces everywhere. – Ertha