[Tutor] I Give Up. - Follow up post
Danny Yoo
dyoo at hkn.eecs.berkeley.edu
Tue Jul 4 20:41:32 CEST 2006
> I tried it by opening a file , but could find no way to do variable
> variables
Hi Brian,
Look for the concept of dictionaries in Python. "Variable variables" in
languages like PHP and Perl are doable in Python, but a dictionary usually
handles such situations in a safer way.
> and then read it in as a file , which builds an array (AKA dictionary)
> and then just assign thus:
>
> foreach ($filearray as $key => $value)
> {
> $$key = $value
> }
This is not safe in Python, because the $key given could easily be the
name of something that shouldn't be treated as configuration, such as the
built-in functions. It also makes debugging a bit harder if we have
variables in a program that aren't explicitely named.
The safe way to do this is to sandbox these variables in a dictionary.
Conceptually, the pseudocode looks like:
################################
config_options = {}
for (name, value) in the file:
config_options[name] = value
################################
and the real code to do this doesn't look too much different.
Let's look at some of the config-reading code:
> if cfg.has_section("Parameters"):
> myparams = cfg.items("Parameters")
> for item in myparams:
> parameter[item[0]] = item[1]
> else:
> log_error("Parameters","not found")
> if cfg.has_section("Ports"):
> ports = cfg.items("Ports")
> for port in ports:
> watch_port[port[0]] = port[1]
> else:
> log_error("Ports","Not Found")
> if cfg.has_section("Hosts"):
> hostnames = cfg.items("Hosts")
> for hostname in hostnames:
> watch_hosts[hostname[0]] = hostname[1]
> else:
> log_error("Hosts","Not Found")
> if cfg.has_section("IP Addresses"):
> ips = cfg.items("IP Addresses")
> for ip in ips:
> watch_ips[ip[0]] = ip[1]
> else:
> log_error("IP Addresses","Not Found")
> if cfg.has_section("Alerts"):
> alerts_to = cfg.items("Alerts")
> else:
> log_error("Hosts","Not Found")
There's a lot of repetition here. When we have the temptation to copy and
paste, try to see if a helper function can do some lifting.
In fact, there's a bug there because of the copy-and-paste. If there are
no Alerts, the system will spuriously blame Hosts. I resent being blamed
for things I don't do, and I'm sure my programs feel the same. *grin*
Here's a possible refactoring:
#########################################################
def read_config_section(section_name, output_dictionary):
if cfg.has_section(section_name)
section = cfg.items(section_name)
else:
log_error(section_name, "Not Found")
for key_value in section:
output_dictionary[key_value[0]] = key_value[1]
#########################################################
Once we have this, we can then do:
read_config_section("Parameters", parameter)
read_config_section("Ports", watch_port)
...
and eliminate a lot of that repetitive code.
Does this make sense? Feel free to ask more questions.
More information about the Tutor
mailing list