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.
CodePudding user response:
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)