views:

397

answers:

3

I would like to define globals in a "programmatic" way. Something similar to what I want to do would be:

definitions = {'a': 1, 'b': 2, 'c': 123.4}
for definition in definitions.items():
    exec("%s = %r" % definition)  # a = 1, etc.

Specifically, I want to create a module fundamentalconstants that contains variables that can be accessed as fundamentalconstants.electron_mass, etc., where all values are obtained through parsing a file (hence the need to do the assignments in a "programmatic" way).

Now, the exec solution above would work. But I am a little bit uneasy with it, because I'm afraid that exec is not the cleanest way to achieve the goal of setting module globals.

+7  A: 

You can set globals in the dictionary returned by globals():

definitions = {'a': 1, 'b': 2, 'c': 123.4}
for name, value in definitions.items():
    globals()[name] = value
Ned Batchelder
+1  A: 

You're right, exec is usually a bad idea and it certainly isn't needed in this case.

Ned's answer is fine. Another possible way to do it if you're a module is to import yourself:

fundamentalconstants.py:

import fundamentalconstants

fundamentalconstants.life_meaning= 42

for line in open('constants.dat'):
    name, _, value= line.partition(':')
    setattr(fundamentalconstants, name, value)
bobince
I prefer Nadia's `import[__name__]` to hardcoding this module's name.
Alex Martelli
Interesting: I had not thought of that! It's true that it is not robust against changing the module file name, but it's still an interesting idea that I prefer to my `exec`!
EOL
+5  A: 

Here is a better way to do it:

import sys
definitions = {'a': 1, 'b': 2, 'c': 123.4}
module = sys.modules[__name__]
for name, value in definitions.iteritems():
    setattr(module, name, value)
Nadia Alramli
Maybe you could describe why this is better?
tom10
@tom10, there's no documented guarantee that _changes_ to `globals()` will actually persist the changes to the underlying module. It works today, might break tomorrow. Nadia's solution OTOH is solid (hence +1 from me;-).
Alex Martelli
I like this way of doing it, but about locals() and globals(): the current docs seem to imply it will always work:locals: Update and return a dictionary representing the current local symbol table. Warning: The contents of this dictionary should not be modified; changes may not affect the values of local variables used by the interpreter. globals: Return a dictionary representing the current global symbol table. This is always the dictionary of the current module.Maybe the docs need to be tweaked up...
Ned Batchelder
Ah ah! `sys.modules[…]` is the key… Thank you for pointing it out! Time to study the documentation of `sys`…
EOL