Giving this dictionary:
>>> options = {'DATABASES': {'default': {'ENGINE': 'django.db.backends.sqlite3'}}}
What would be the best way to get this?:
>>> foo(options)
>>> print DATABASES
{'default': {'ENGINE': 'django.db.backends.sqlite3'}}
I am solving this as locals().update(options), but I was thinking, if there is maybe a better solution.
import inspect
allowed_vars = set(["min_", "max_", "path", ...])
def update_globals(dic):
caller_frame = inspect.currentframe(1)
globals = caller_frame.f_globals
# here, you _could_ simply do globals.update(dic)
# but it is evil
for 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)
# continue
globals[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})
>>> a
5
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
def myfunc():
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).
As goldmab noted, modifying the output of locals() inside a function won't work:
SyntaxError: invalid syntax
>>> def foo():
... 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' is not defined
This isn't really a very clean way either, but it would do the job:
>>> def foo():
... 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') ; ..."
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With