Это довольно странная вещь, но она выполнима.
Ваш вызов exec выполняет оператор f()
в предоставленных глобальных переменных. Он не выполняет body из f
в предоставленных глобальных переменных. Предоставленные глобальные переменные используются в неправильном кадре стека. Чтобы получить доступ к этим глобальным переменным из f
, вы можете использовать проверка стека :
import inspect
def f():
log = inspect.currentframe().f_back.f_globals['log']
log('Hi')
exec('f()', {'f': f, 'log': print})
Если вы хотите выполнить тело f
с предоставленными глобалами, а не просто получить доступ к глобалам, вам нужно сделать копию f
с вашими собственными глобальными глобалами:
import types
my_f = types.FunctionType(f.__code__,
{'log': print},
f.__name__,
f.__defaults__,
f.__closure__)
my_f()
Конструктор типа функции является своего рода документированным; его нет в онлайн-документах, но задокументировано в строке документации типа функции:
function(code, globals[, name[, argdefs[, closure]]])
Create a function object from a code object and a dictionary.
The optional name string overrides the name from the code object.
The optional argdefs tuple specifies the default argument values.
The optional closure tuple supplies the bindings for free variables.