1

I had this code:

def test(variable, customCode = ""):

    if variable > 1:
        print(">1")

    if customCode != "":
        exec(customCode)

    if foo == 1:
        print("Success")

numb = 12
code = "if variable > 1: foo = 1"

test(numb, code)

Which, when executed, gives this error:

Error 1

So, then, I added foo = 0 at the beginning of the code, and got this output:

Issue 2

Now, obviously, it should also be outputting Success, but it isn't.

What's the issue?

Using Python 3.

4
  • The code executes fine, with >1 then a line break and Success. Commented Jul 12, 2015 at 20:35
  • @l'L'l, are you using python3? Commented Jul 12, 2015 at 20:36
  • @PadraicCunningham, I tried both 2.7.6 and 3.4.3 (in Python3 it failed miserably), sorry I didn't mention that. Your answer got me curious — would that be considered a form of scoping? Commented Jul 12, 2015 at 21:35
  • 1
    @l'L'l, basically yes, unless we pass our own dict locals() gets used, any changes to it won't be reflected outside the scope of the exec. docs.python.org/3.5/library/functions.html#locals Commented Jul 12, 2015 at 21:55

2 Answers 2

6

The correct way is to pass a dict to exec in python 3 and lookup by key, in python2 your code would work as is because exec is a statement as opposed to a function in python3:

def test(variable, customCode = ""):
    d = {"variable":variable}
    if customCode != "":
        exec(customCode, d)
    if d["foo"] == 1:
        print("Success")

numb = 12
code = "if  variable > 1: foo = 1"

test(numb, code)

Output:

In [13]: numb = 12

In [14]: code = "if  variable > 1: foo = 1"

In [15]: test(numb, code)
Success

exec

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.

You also need to catch the case where your if variable > 1 is False as you will never exec the code so foo will never be added.

Sign up to request clarification or add additional context in comments.

2 Comments

Okay, your answer led me to my solution, which I am about to post. Thanks.
After a couple of years of never accepting a solution (I have no idea why), I think your answer is better than mine, so I'm giving you the check.
0

Reading @Padraic Cunningham's post gave me an idea, which worked as a solution:

It's simple: instead of just doing : foo = 1, do : global foo; foo = 1.

Changed code:

def test(variable, customCode = ""):

    if variable > 1:
        print(">1")

    if customCode != "":
        exec(customCode)

    if foo == 1:
        print("Success")

numb = 12
code = "if variable > 1: global foo; foo = 1"

test(numb, code)

The issue is that exec() is a function rather than a statement in Python 3, so foo was being used as a local variable. (Source: @Padraic Cunningham)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.