That is because the
exec runs in the global scope. When Python sees a variable that is not assigned to in the local scope, it is assumed to be a global variable, so when
exec creates a new local variable, the load still fails because it looks into the globals dictionary.
But you can do this:
def foo():
exec("a = 1")
return locals()['a']