Найти - Пользователи
Полная версия: Переменная, созданная в "exec", недоступна после "exec", хотя присутствует в locals(), vars() и dir(). Легализовать переменную Возможно?
Начало » Python для экспертов » Переменная, созданная в "exec", недоступна после "exec", хотя присутствует в locals(), vars() и dir(). Легализовать переменную Возможно?
1 2
MLM
Код:
 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
def check_test():
    print('*globals().keys() не меняется ->', *globals().keys())
    print('    До всего')
    print('locals() ->', locals())
    print('dir() ->', dir())
    print('    До "exec"')
    print('a = 5')
    a = 5
    print('locals() ->', locals())
    print('dir() ->', dir())
    exec('''
print('    Внутри "exec"')
print('b = 3')
b = 3
print('locals() ->', locals())
print('dir() ->', dir())
print('a ->', a)
print('locals()["b"] ->', locals()['b'])
print('b ->', b)
        ''')  # , globals(), locals()
    print('    После "exec"')
    print('locals() ->', locals())
    print('dir() ->', dir())
    print('a ->', a)
    print('locals()["b"] ->', locals()['b'])
    print(end='b -> ')
    try:
        print(b)
    except Exception as e:
        print(e)
    exec('''
print('    Внутри второго "exec"')
print('b ->', b)
        ''')
    print('    После второго "exec"')
    print(end='b -> ')
    try:
        print(b)
    except Exception as e:
        print(e)
if __name__ == '__main__':
    check_test()
На выходе:
*globals().keys() не меняется -> __name__ __doc__ __package__ __loader__ __spec__ __builtins__ __file__ check_test
До всего
locals() -> {}
dir() -> []
До "exec"
a = 5
locals() -> {'a': 5}
dir() -> ['a']
Внутри "exec"
b = 3
locals() -> {'a': 5, 'b': 3}
dir() -> ['a', 'b']
a -> 5
locals()["b"] -> 3
b -> 3
После "exec"
locals() -> {'a': 5, 'b': 3}
dir() -> ['a', 'b']
a -> 5
locals()["b"] -> 3
b -> name 'b' is not defined
Внутри второго "exec"
b -> 3
После второго "exec"
b -> name 'b' is not defined
Rodegast
> Переменная, созданная в “exec”, недоступна после “exec”, хотя присутствует в dir() и locals(). Легализовать переменную Возможно?

Ну как бы:
 >>> exec("a=3")
>>> a
3
P.S. Никогда не используй exec.
MLM
1. Спасибо за попытку помочь.
2. Перед тем как задавать вопрос, я всяко пробовал, и что в интерпретаторе работает знаю. Нормально тоже работает, если код в глобальной области. Но интересует именно вопрос “легализации” переменной в локальной области, согласно locals().
3. При использовании “exec”, код для него будет генерировать сама программа, т.е. ничего неожиданного не будет.
4. Правда, полученные значения переменных будут использоваться кодом функции “eval”, который написан своим человеком, не из Интернета. Но тем не менее, этот код будет пропущен через фильтр допустимых слов, что должно обезопасить от возможных неожиданностей.
5. Может подскажете ещё какие то меры.
FishHook
 def foo():
    exec("a=1", {}, locals())
    print(locals())
foo()
MLM
Спасибо за попытку помочь. О доступе через locals() знаю. В коде есть строка
     print('locals()["b"] ->', locals()['b'])
Передать вместо globals() пустой словарь - хорошая идея, но тогда даже такой код нельзя использовать:
     exec('''
globals()["b"] = b
        ''')
Хотя после него переменная уже доступна и значение её правильное, но она глобальная.
Но интересует именно вопрос “легализации” переменной “b” в локальной области, согласно locals(), если это вообще возможно.
Rodegast
 >>> def foo():
...     s = {}
...     exec("a=1", {}, s)
...     print(s.get('a'))
...
>>> foo()
1
MLM
Надо чтобы
     print(b)
работало. Что бы “b” было в локальной области, если это возможно.
Rodegast
> Что бы “b” было в локальной области, если это возможно.

 b = s.get('a')
MLM
С переменной “a” проблем нет, с “b” проблемы
     b = locals()['b']
#    b = s['b']  # будет тоже самое
KeyError: 'b'
Похоже, сделать доступной локальную переменную “b” из “exec” в локальной области “check_test” невозможно.
Rodegast
> С переменной “a” проблем нет, с “b” проблемы

Ну так и быть…
 >>> def foo():
...     s = {}
...     exec("b=3", {}, s)
...     b = s.get('b')
...     print(b)
...
>>> foo()
3
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB