[Tutor] executing dynamic code with exec?

Steven D'Aprano steve at pearwood.info
Fri Dec 2 06:25:40 CET 2011


Chris Hare wrote:

> What I am trying to do is create a set of variables based upon the table
> names in the table variables.  I have similar code which dynamically
> creates check buttons and the associated grid.  But I suspect those won't
> work either.
> 
> What have I got wrong?

Everything! <wink>

Seriously though, your basic approach is the wrong approach. Don't try to 
create dynamic variables like that. Suppose you succeed:

varName = 'x'  # read from a file, or something
exec('%s = 1' % varName)  # creates the variable x

Great. Now you have a variable x. Later on, how do you use it?

# much later on in your code...
y = x + 1

But that won't work, because you don't know that it's called x! If you knew it 
was called x, you would have just written x = 1 early and not needed exec.

Working with dynamic variable names is a pain and a nightmare. Don't do it. 
Even if you succeed, you are making a rod for your own back: maintaining such 
code is horrible.

The right way to do this is almost always to use a data structure that maps 
names to values, in other words, a dict.

varName = 'x'  # read from a file, or something
data = {varName: 1}
# ...
# much later
y = data[varName] + 1


In this case, something like:


names = ["Farm", "Animals", "AnimalTypes", "Users", "Roles",
     "Capabilities", "Pedigrees", "ChipMaker", "Owner", "Providers",
     "RegistryL"
     ]
self.cbReadTable = {}
for name in names:
     self.cbReadTable[name] = IntVar()


And that's it. Instead of retrieving instance.cbFarmRead, use 
instance.cbReadTable['Farm'].

If you absolutely must use instance attributes, perhaps because you think 
you're writing Javascript <wink>, then:

for name in names:
     name = 'cb' + name 'Read'
     setattr(self, name, IntVar())


And best of all, you avoid the code injection security vulnerability where 
somebody manages to fool your code into using a list of table names like:

names = ["Farm", "Animals", "AnimalTypes", "Users", "Roles",
     "Capabilities", "Pedigrees",
     "ChipMaker=1;import os;os.system('echo you are pwned rm-rf haha');",
     "Owner", "Providers", "RegistryL"
     ]


Hope your backups are really good.

http://xkcd.com/327/



-- 
Steven



More information about the Tutor mailing list