1

When I have exec() in defined function it is not working ('NameError: name 'a' is not defined'):

def abc():
    qwerty = "a = 2"
    exec(qwerty)
abc()
print(a)

but, when I won't use def, it is working:

qwerty = "a = 2"
exec(qwerty)
print(a)

How can I "repair" it, or are there other similar solutions? (I can't execute this at start, I need to call that function in the middle of the program)

5
  • 2
    When you execute a = 2 inside the function, it gets defined in the local scope, then once you get to print(a) you are outside that scope. You could probably declare the variable global at the start of abc. Commented Apr 4, 2021 at 11:32
  • 2
    Does this answer your question? Running exec inside function Commented Apr 4, 2021 at 11:33
  • Check LEGB variable scope. Commented Apr 4, 2021 at 11:37
  • exec() to dynamically execute Python code- this can be a string or some object code. When it is object code, Python executes it. But exec() doesn’t return a value; it returns None. Hence, we cannot use return and yield statements outside function definitions. Commented Apr 4, 2021 at 11:41
  • 1
    Also, obligatory warning: exec should almost never be used unless you are absolutely sure it's the only and correct solution. Many new programmers learn about exec or eval and think they are solutions to their problems, when 99.99% of the time there are much better ways to solve your problem. Code with exec and eval usually becomes very hard to read or understand for a professional programmer, and they potentially creates many security issues in your program. They're also slower than the alternatives. I've yet to ever needed to use, or seen, them in a production program. Commented Apr 4, 2021 at 11:50

3 Answers 3

2

My answer is similar to @Cyrill's answer but with some subtle differences.
There are 3 ways to call the exec function:

  1. With 1 argument, e.g. exec('a = 2'). This will execute the statement in the current scope and thus create a local variable.
  2. with 2 arguments, e.g. exec('a = 2', globals()). This will execute the statement in the suplied global namespace, which is also the current global namespace (returned by globals()). This will mutate the global namespace.
  3. with 3 arguments, e.g. exec('a = 2', globals(), loc). This will execute the statement in the suplied local namespace (the third argument) using the suplied global namespace as the global namespace. This will mutate the local namespace.

By using the second way we can execute code in the global namespace, so:

def abc():
    qwerty = 'a = 2'
    exec(qwerty, globals())
abc()
print(a)  # outputs 2
Sign up to request clarification or add additional context in comments.

Comments

1

You are missing a parameter on exec() function

variables used inside the exec function cannot be accessed as if they where declared globally

a workaround would be to pass 2 dictionaries in exec()
as such, i normally would do that like this..

loc = {}
def abc():
    qwerty = "a = 2"
    exec(qwerty, globals(), loc)
abc()
print(loc['a'])

which would then output 2

Comments

0

In my case, the Riven's comment helped me a lot:

loc = {}
def abc():
    qwerty = "a = 2"
    exec(qwerty, globals(), loc)
abc()
print(loc['a'])

In my case I had main script which called a second script. I needed to use the "c" variable within the second script. Therefore I used locals(),loc as arguments for exec().

loc = {}
a = 10
b = 5
def abc(a,b):
    qwerty = "c = %d + %d"%(a,b)
    exec(qwerty, locals(), loc)
    c = loc['c']
    d = c+2
    print(d)

abc(a,b)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.