Python exec code in run globals

Cannot change global variables in a function through an exec() statement?

Why can I not change global variables from inside a function, using exec()? It works fine when the assignment statement is outside of exec(). Here is an example of my problem:

>>> myvar = 'test' >>> def myfunc(): . global myvar . exec('myvar = "changed!"') . print(myvar) . >>> myfunc() test >>> print(myvar) test

4 Answers 4

Per the docs, the exec statement takes two optional expressions, defaulting to globals() and locals() , and always performs changes (if any) in the locals() one.

So, just be more explicit/specific/precise.

>>> def myfunc(): . exec('myvar="boooh!"', globals()) . >>> myfunc() >>> myvar 'boooh!' 

. and you’ll be able to clobber global variables to your heart’s contents.

A small clarification — the two optional parameters don’t default to globals() and locals(). If they did, then they wouldn’t have to be specified.

The docs warn against using locals() i tried it anyways and it didnt work, but globals did. however i couldn’t use the globals with locals during assignment. yikes.

To add to Alex’s answer: although when you omit the locals/globals arguments they default to the locals and globals of the caller, this only a convenience hack; it does not mean they are inheriting the full execution context of the caller. In particular:

a. nested scope cells are not available to the execed code. So this fails:

def f(): foo= 1 def g(): exec('print foo') g() f() 

b. global declarations do not carry over into the execed code. So by default as in your example, written variables are put in the locals dictionary. However, you could make it work by saying

exec('global myvar\nmyvar = "changed!"') 

You don’t really want to be doing this if you can help it. global already isn’t nice and exec is pretty much a code smell in itself! You wouldn’t want to combine them unless there was really no alternative.

Читайте также:  Joomla nginx php fpm

Источник

Метод exec() в Python

По сути, метод Python exec() выполняет переданный набор кода в виде строки. Это очень полезно, так как практически поддерживает динамическое выполнение. Синтаксис метода приведен ниже.

exec(object, globals, locals)

Здесь object может быть строкой, объектом открытого файла или объектом кода.

  • Для строки — строка анализируется как набор операторов Python, который затем выполняется (если не возникает синтаксическая ошибка).
  • Для открытого файла — файл анализируется до EOF и выполняется.
  • Для объекта кода — просто выполняется.

И два дополнительных аргументов globals и locals должны быть словари , используемые для глобальных и локальных переменных.

Exec() метод

Давайте попробуем понять, как он работает, на примере.

>>> exec("print('Hey!')") Hey! >>> exec("print(6+4)") 10

Из приведенного выше фрагмента кода ясно, что операторы print() успешно выполняются методом exec() и мы получаем желаемые результаты.

Работа с методом Python exec()

Теперь давайте сразу перейдем к некоторым примерам, изучающим, как метод exec() работает в Python с параметрами globals и locals и без них.

1 Без глобальных и локальных параметров

В предыдущем примере мы просто выполнили некоторый набор инструкций в Python, передав аргумент объекта методу exec() . Но мы не видели имена в текущей области.

Теперь давайте воспользуемся методом dir(), чтобы получить список текущих методов и имен с включенным math модулем перед вызовом метода exec() .

from math import * exec("print(pow(2, 5))") exec("print(dir())")
32.0 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

Как видите, различные методы, включая builtins , а также из math модуля, прямо сейчас находятся в текущей области видимости и доступны для метода exec() .

Читайте также:  Flex css background image

Это создает большую проблему безопасности, когда вы думаете о выполнении динамического кода Python. Пользователь может включать некоторые модули для доступа к системным командам, которые даже могут привести к сбою вашего компьютера.

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

2 С параметром globals

Python позволяет нам передавать и указывать только те методы, к которым мы хотим, чтобы метод exec() имел доступ (в форме словаря) из встроенного модуля.

def squareNo(a): return a*a exec('print(squareit(10))',>) exec("print(dir())")
100 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'squareNo']

В приведенном выше коде мы передали словарь, содержащий методы squareNo() (сопоставленные с настраиваемым именем squareit) и print() .

Обратите внимание: использование любого другого метода из встроенного метода вызовет TypeError .

3 С параметром locals

Когда мы передаем только local параметр (словарь), по умолчанию все встроенные методы также становятся доступными до тех пор, пока мы явно не исключим их.

Посмотрите на пример ниже, хотя мы указали словарь locals все встроенные и математические методы модуля доступны в текущей области.

from math import * def squareNo(a): return a*a #global And local parameters exec('print(pow(4,3))', ) exec("print(dir())")
64 ['__annotations__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', 'modf', 'nan', 'pi', 'pow', 'radians', 'remainder', 'sin', 'sinh', 'sqrt', 'squareNo', 'tan', 'tanh', 'tau', 'trunc']

Следовательно, теперь явно исключая встроенные функции.

from math import * def squareNo(a): return a*a #explicitly excluding built-ins exec('print(pow(4,3))', ,) exec("print(dir())")
Traceback (most recent call last): File "C:/Users/sneha/Desktop/test.py", line 7, in exec('print(pow(4,3))', ,) File "", line 1, in TypeError: 'NoneType' object is not subscriptable

В приведенном выше коде ограничение метода на использование только переданных (локальных) методов практически делает недоступным метод pow() . Следовательно, при его запуске мы получаем TypeError .

Читайте также:  Посчитать количество цифр в числе java

exec() сравнение с eval()

Между методами eval() и exec() есть два основных различия, хотя они выполняют почти одинаковую работу.

  1. eval() может выполнять только одно выражение, тогда как exec() может использоваться для выполнения динамически созданного оператора или программы, которая может включать циклы, операторы if-else , определения функций и class ,
  2. eval() возвращает значение после выполнения определенного выражения, тогда как exec() в основном ничего не возвращает и просто игнорирует значение.

Источник

Setting variables with exec inside a function

«I just started self teaching Python..» sounds like they’re is just trying to wrap their head around a new language.

2 Answers 2

You’re almost there. You’re trying to modify a global variable so you have to add the global statement:

old_string = "didn't work" new_string = "worked" def function(): exec("global old_string; old_string = new_string") print(old_string) function() 

If you run the following version, you’ll see what happened in your version:

old_string = "didn't work" new_string = "worked" def function(): _locals = locals() exec("old_string = new_string", globals(), _locals) print(old_string) print(_locals) function() 

The way you ran it, you ended up trying to modify the function’s local variables in exec , which is basically undefined behavior. See the warning in the exec docs:

Note: The default locals act as described for function locals() below: modifications to the default locals dictionary should not be attempted. Pass an explicit locals dictionary if you need to see effects of the code on locals after function exec() returns.

and the related warning on locals() :

Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

Источник

Оцените статью