Skip to content Skip to sidebar Skip to footer

How Can I Load All Keys From A Dict As Local Variables, A Better Aproach?

Giving this dictionary: >>> options = {'DATABASES': {'default': {'ENGINE': 'django.db.backends.sqlite3'}}} What would be the best way to get this?: >>> foo(optio

Solution 1:

import inspect

allowed_vars = set(["min_", "max_", "path", ...])
defupdate_globals(dic):
    caller_frame = inspect.currentframe(1)
    globals = caller_frame.f_globals
    # here, you _could_ simply do globals.update(dic) # but it is  evilfor key, value in dic.items():
        #here you should carefully verify each key, and value for not#not dangerous pairs, with stuff like:#if key not in allowed_vars:#    sys.stderr.write("Warning: invalid variable in configuration update\n")#     continue#if type(value) not in (string, int, float):#    #(issue error)#    continueglobals[key] = value

Example:

>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> update_globals({"a": 5})
>>> a5

update 2016-06 A couple of weeks ago I had put together the extradict Python package - it is available on pypi now. One of its features is the MapGetter context manager that allows exactly what is being asked for by doing something along:

from extradict import MapGetter

defmyfunc():
    options = {'DATABASES': {'default': {'ENGINE': 'django.db.backends.sqlite3'}}}
    with MapGetter(options) as options:
         from options import DATABASES
 ...

And other normal "from .... import .... " usages, but from a dictionary or mapping object (including a default dict).

Solution 2:

As goldmab noted, modifying the output of locals() inside a function won't work:

SyntaxError: invalid syntax
>>> deffoo():
... locals().update({'a': 1})
... print a
... >>> foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in foo
NameError: global name 'a'isnot defined

This isn't really a very clean way either, but it would do the job:

>>>deffoo():...    options = {'DATABASES': {'default': {'ENGINE': 'django.db.backends.sqlite3'}}}...for k, v in options.items():...exec('%s = v' % k)...print DATABASES...>>>foo()
{'default': {'ENGINE': 'django.db.backends.sqlite3'}}

Note, by the way, that each key in your dict would need to be ok as a variable. So for example, if the dictionary contained 'DATABASE-USERNAME' as a key, trying to assign that to a variable would cause an exception. Further, doing this would make you vulnerable to code injection attacks if you get the options dictionary from an untrustworthy source. (A key could say something like, "import os ; os.system('sudo adduser scriptkiddie') ; ..."

Solution 3:

I think what you want is simply:

globals().update(**options)

Solution 4:

You can't modify function locals at runtime, since the list of local variable names is a static part of the compiled function object.

>>>defa(): b = 5...>>>a.func_code.co_varnames
('b',)

This will work in the global scope only because locals() is the same as globals() there, and global variables are stored in a dictionary, which is dynamic (unlike function locals).

>>> locals() isglobals()
True

It looks like you're updating the values in a Django settings module from another source. I wouldn't say this is necessarily bad, but you should use globals() instead of locals() for the sake of clarity.

Post a Comment for "How Can I Load All Keys From A Dict As Local Variables, A Better Aproach?"