для большей ясности.

ставление этого словаря:

>>> options = {'DATABASES': {'default': {'ENGINE': 'django.db.backends.sqlite3'}}}

Каков был бы лучший способ получить это?

>>> foo(options)
>>> print DATABASES
{'default': {'ENGINE': 'django.db.backends.sqlite3'}}

Я решаю это как localals (). Update (options), но я подумала, может быть, есть лучшее решение.

 user39576010 янв. 2011 г., 22:04
Тебе лучше этого не делать. Потому что это означает перезапись ваших переменных с помощью пользовательского ввода, что только на один шаг вышеeval, Просто продолжай со словарем.
 user39576010 янв. 2011 г., 20:32
Лучший способ не делать такие опасные вещи в первую очередь. И, к счастью, одна функция не сможет дурачиться с текущим пространством имен (на самом деле может, с глобальным и, возможно, с большим, если вы используете злой хакерский рефлекс, но даже не думайте об этом!)
 Mario César10 янв. 2011 г., 21:38
@delnan Я понимаю, что использование locals () ужасно. Посмотрите, после разбора файла конфигурации я получаю словарь опций, поэтому Как заменить значения значений по умолчанию в настройках без использования locals () ¿

Ответы на вопрос(4)

Решение Вопроса
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

Пример:

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

обновление 2016-06 Пару недель назад я собралextradict Пакет Python - доступен насейчас пипи, Одной из его особенностей являетсяMapGetter менеджер контекста, который позволяет именно то, что требуется, делая что-то вместе:

from extradict import MapGetter

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

И другие обычные "from .... import ...." использования, но из словаря или объекта отображения (включая dict по умолчанию).

 jsbueno12 янв. 2011 г., 17:09
Само по себе опасно не модификация локальных или глобальных переменных - это часть динамизма Python, и мы должны использовать его. Опасным является сбор данных из непроверенного источника (обычно ввод удаленных пользователей) и преобразование их в «живые» объекты python в работающей программе. При условии, что вы добавляете меры предосторожности, о которых я говорю выше, с этим кодом не должно возникнуть никаких проблем.
 Mario César12 янв. 2011 г., 14:40
Я знаю, что модификация локальных или глобальных переменных - это что-то опасное, но ваш метод работает так, как мне нужно. Вероятно, в будущем я бы изменил поведение моего парсера для настройки

Я думаю, что вы хотите просто:

globals().update(**options)

поскольку список имен локальных переменных является статической частью скомпилированного функционального объекта.

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

Это будет работать в глобальном масштабе только потому, чтоlocals() такой же какglobals() там, и глобальные переменные хранятся в словаре, который является динамическим (в отличие от локальных функций).

>>> locals() is globals()
True

Похоже, вы обновляете значения в модуле настроек Django из другого источника. Я бы не сказал, что это обязательно плохо, но вы должны использоватьglobals() вместоlocals() для большей ясности.

изменение вывода locals () внутри функции не будет работать:

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

Это не совсем чистый способ, но он бы справился с работой:

>>> 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'}}

Заметьте, кстати, что каждый ключ в вашем dict должен быть в качестве переменной. Так, например, если словарь содержит «DATABASE-USERNAME» в качестве ключа, попытка присвоить его переменной вызовет исключение. Кроме того, выполнение этого сделает вас уязвимым для атак внедрения кода, если вы получите словарь опций из ненадежного источника. (Ключ может сказать что-то вроде: "import os; os.system ('sudo adduser scriptkiddie'); ..."

Ваш ответ на вопрос