Namespaces, multiple assignments, and exec()

John O'Hagan mail at johnohagan.com
Sun Dec 21 21:02:31 EST 2008


On Sat, 20 Dec 2008, John O'Hagan wrote:
> On Sat, 20 Dec 2008, Terry Reedy wrote:
> > John O'Hagan wrote:
> > > I have a lot of repetitive assignments to make, within a generator,
> > > that use a function outside the generator:
> > >
> > > var1 = func("var1", args)
> > > var2 = func("var2", args)
> > > var3 = func("var3", args)
> > > etc...
> > >
> > > In each case the args are identical, but the first argument is a string
> > > of the name being assigned. It works fine but I'd like to reduce the
> > > clutter by doing the assignments in a loop. I've tried using exec():
> > >
> > > for name in name_string_list:
> > >     exec(name + ' = func(\"' + name + '\", args)')
> > >
> > > but in the local namespace it doesn't understand func(), and if I give
> > > it globals() it doesn't understand the args, which come from within the
> > > generator.
> > >
> > > What's a good way to do this kind of thing?
> >
> > Put everything in your own namespace
> >
> > myvars={}
> > for name in namelist:
> >    myvars[name]=func(name,args)
>
> Likely I'm missing something, but don't I still have to do
>
> var1 = myvars['var1']
> var2 = myvars['var2']
> var3 = myvars['var3']
> ...etc.
>
> to make the assignments?

And of course I am missing the fact that I can now do the exec loop over 
myvars{} in the local namespace.

Doing this, however, exposed some behaviour that surprises me. Inside my 
generator, doing:

exec('foo = 7') in locals()
print foo
foo = 3

produces an UnboundLocalError. In case it's relevant, the error I get inside 
the generator if I don't specify local()s is:

SyntaxError: unqualified exec is not allowed in function 'sequence_engine' it 
contains a nested function with free variables

But doing the same thing in a simple test generator, even if it calls outside 
functions, works as I expect. 

Removing any subsequent reassignments of the same name fixes the error, and as 
it happens I can do this, but I'm curious, without me posting the whole 
generator (it's long), why doesn't the above exec() assignment work in that 
context? 

Thanks,

John









More information about the Python-list mailing list