Re: [Tutor] executing dynamic code with exec?
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 ch...@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@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
[Tutor] executing dynamic code with exec?
I have this code chunk: tables = [Farm, Animals, AnimalTypes,Users,Roles,Capabilities,Pedigrees,ChipMaker,Owner,Providers,RegistryL] for x in tables: cmd = self.cb + x + Read = IntVar() exec cmd in locals(), globals() When the code is executed, I get the following error: File z.py, line 4398 exec cmd in locals(), globals() SyntaxError: function 'showRoles' uses import * and bare exec, which are illegal because it contains a nested function with free variables 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? Thanks! Chris___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] executing dynamic code with exec?
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@python.org To unsubscribe or change subscription options: http://mail.python.org/mailman/listinfo/tutor