[Tutor] executing dynamic code with exec?
Chris Hare
chare at labr.net
Fri Dec 2 13:39:00 CET 2011
Thanks Steve for your help (and the humor). I can see that it was a bad idea with your explanation. (I just didn't want to type all that extra code :-))
I am going to re-write it using your dict approach - that looks a lot cleaner
Thanks!
Chris Hare
chare at labr.net
http://www.labr.net
On Dec 1, 2011, at 11:25 PM, Steven D'Aprano wrote:
> 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
>
> _______________________________________________
> Tutor maillist - Tutor at python.org
> To unsubscribe or change subscription options:
> http://mail.python.org/mailman/listinfo/tutor
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20111202/6aa46f39/attachment.html>
More information about the Tutor
mailing list