A problem with exec statement

TPJ tprimke at interia.pl
Fri Apr 14 06:40:26 EDT 2006


> <snip>
> So when you exec 'a = "B"' in globals(), locals() you might think you
> were changing the local namespace. In fact you are changing a copy of
> the local namespace:
> <snip>

Well, that explains much, but not all that I want to be explained. Why?
Because now I understand, that by invoking

exec "a = 'B'" in globals(), locals()

I can modify only *copies* of the global and local namespaces dicts,
not the dicts themselves. OK, that's why my code doesn't work as I want
it to work.

But why on Earth *the same code* will work, if I remove the assignments
from the marked lines? Why then operating on copies of the local
namespaces dicts *will work* ?

> (...) Even allowing for the
> difficulties you've already experienced, it's nearly always better in
> practical cases to use assignment to the keys of a dictionary. Then no
> exec is required, and you have direct control over your own namespace.

Well... Is this a sugestion, that instead of messing up with the exec
statements used to modify local namespaces I should use dictionaries?

Perhaps you're right. In fact, the problem, that I'm trying to solve is
as follows:

def funcA():

  def funcB():
    ...
    var1, var2, var3, ..., varN = ( None, ) * N
    t = ( (regexp1, 'var1'), (regexp2, 'var2'), ..., (regexpN, 'varN')
)
    for regexp, var_name in t:
      match = regexp.match( some_string )
      if match != None:
          # now the *magic* exec statement comes...
        exec var_name + ' = match.groups()[0]' in globals(), locals()
    return var1, var2, var3, ..., varN

  ...
  k1, k2, k3, ..., kN = funcB()

Of course, the code presented above doesn't work. It works, if one
change is done in the function funcB:

  def funcB():
    ...
    # no creation of any local variables called var1, var2, ..., varN
here
    t = ( (regexp1, 'var1'), (regexp2, 'var2'), ..., (regexpN, 'varN')
)
    for regexp, var_name in t:
      match = regexp.match( some_string )
      if match != None:
          # now the *magic* exec statement comes...
        exec var_name + ' = match.groups()[0]' in globals(), locals()
      else:
          # here we put the code, that will assign None to the variable
        exec var_name + ' = None'
    return var1, var2, var3, ..., varN

But I *still* don't understand, why this code works, if I operate on a
copy of the local namespace dict...

Of course, I can do the same thing in a different matter - by using a
dictionary. And perhaps I will. But I still want to know, how the exec
statement works.

* * *

My problem is more complicated, that the presented example. In general,
my problem is: how to create a local variable by executing the Python
code, that isn't known at the moment of writing the program? In another
words: I have to create a local variable, whose name will be known at
the runtime, in a nested function.

Is it possible, or have I to use dictionaries, instead of exec
statement used to modify local namespaces?




More information about the Python-list mailing list