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.
-
Exec just runs a Python command from a string. If your statement is valid when typed in Python 3 it should work fine.Matt– Matt2022年08月07日 23:49:42 +00:00Commented Aug 7, 2022 at 23:49
1 Answer 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)