0

I am using some old code base that was initially written in python2. The devs say they have ported it to python3 however I found a all the code that uses exec is completely broken. Below you can find an example like the one I am trying to fix:

def function_with_exec(table):

    (sess, tgt) = 3, None
    try:
        exec("ec = some_object.{}_get_entry_count(sess_hdl=sess, dev_tgt=tgt)".
             format(table))
    except AttributeError:
        return []

    ec = some_function(ec)

When running this code, I get: `UnboundLocalError: local variable 'ec' referenced before assignment.

I have been reading that a way to modify the global ec variable from the exec function is to pass the globals() as second argument. However, when I do that, then the variables sess and tgt which are also used in the expression, become undefined too.

I really do not find a way to solve this.

1
  • Exec just runs a Python command from a string. If your statement is valid when typed in Python 3 it should work fine. Commented Aug 7, 2022 at 23:49

1 Answer 1

1

Python thinks ec is a local variable, which hasn't yet been assigned to, and you can't reference it before first assigning to it. Use the global statement at the start of your function, like so:

def function_with_exec(table):
    # ec now refers to the global variable, which presumedly already been as
    global ec
    (sess, tgt) = 3, None
    try:
        exec("ec = some_object.{}_get_entry_count(sess_hdl=sess, dev_tgt=tgt)".
             format(table))
    except AttributeError:
        return []
    
    ec = some_function(ec)

See 7.12. The global statement

The global statement is a declaration which holds for the entire current code block. It means that the listed identifiers are to be interpreted as globals. It would be impossible to assign to a global variable without global, although free variables may refer to globals without being declared global.

You could also remove the call to exec by using getattr instead:

def function_with_exec():
    global ec
    
    (sess, tgt) = 3, None
    try:
        ec = getattr(some_object, f"{table}_get_entry_count")(sess_hdl=sess, 
                                                              dev_tgt=tgt)
    except AttributeError:
        return []
    
    ec = some_function(ec)
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, I was thinking that the getattr would be even a better solution for all this mess. Thanks a lot!

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.