[Tutor] I Give Up. - Follow up post
Brian Gustin
brian at daviesinc.com
Tue Jul 4 22:49:11 CEST 2006
Danny Yoo wrote:
>> 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.
Yeah I am familiar with the concept , and it would work nicely for some
applications, but I couldnt make it work the way I need it to for this
application :)
Reason: It's more to do with the further functions in the application
that I did not paste in the follow up :)
The issue, again is that I want to call a variable by *name* , but I do
not *KNOW* what that variable's name is, exactly
For example, say I have apache running on port 80, apache-ssl on 443,
apache2 on port 81, and Caudium on port 8080 (yes I do have a machine
running not only those servers, but AOLServer, simultaneously)
If I want to configure a protocol to check, *for multiple machines* I
might do
(pseudo function)
Check_Host(machine,protocol,port,last_results)
Now, if I want to iterate over a list of machines , and check each
machine for whatever it was set for (in the config file)
I cannot obviously have a config that says
(Protocol = Port)
http = 80
http = 81
http = 8080
smtp = 25
So the config file requires http to be the first part of the string ,
followed by something to make it unique (I.E. http1, http2, http3)
Now, if I pass each value in turn to check_host, how do I tell what type
of check to make ? (Obviously if I want to get a string from a web page,
I need to SEND a GET request, but if I am checking smtp, I cannot use
that same function, SO.... )
I check for the base of the configuration (if http in protocol: then run
http request, else something else)
so that I can run the correct request type on the correct port , and
maintain a log, but I cannot do that as effectively if it is a
dictionary or list or even a foreach ..
As I said, I have looked at this from every angle I could see, but using
dictionary (which was my *first* choice) did not work the way I needed
it to, nor did simply reading a file to get name value pairs I needed
the name to be an actual variable name..
believe me I have tried dictionaries, Ive tried parsing the file by
other means, but the only way I could get results I needed was through
configparser
>
>> 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.
Yes, I am well aware of the dangers of taking values unchecked into an
array such as this method shows (simplified).. I rarely ever use it, or
if I do, it is on *known* clean data (example, pulling config data out
of a database , reading a .ini file, etc.. not untrusted user input)
I have seen people use this method to extract POST and GET data for
example (untrusted user input) , which I find horrifying :)
>
> 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.
>
Yeah, basically you carry values in a dictionary named by keyname ,
but.. there have been situations where I need the key name as the
variable name , I.E. config_options[name] = value could become
name = value as if it was explicitly defined that way
It's difficult to grasp or even effectively explain the concept or idea,
but sometimes you need to KNOW the key name, *without* knowing the key
name :) (confused yet? hahaha)
>
>
> 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.
Agreed. however I just set this as a preliminary - in no way is this
code finished. :) I actually intended to build a function to do this.
(In perl, I use Switch/Case statements, does Python have anything
similar? - with switch/case, you can set a final default "catch-all" at
which point I log a "unknown event" message )
>
> 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*
Yep. see above comment :-D
>
> 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.
Yeah it makes sense,, a lot of what I posted here is just some
preliminary stuff- related to the O.P. that I could not fnid sufficient
documentation or examples of ConfigParser to get it to do what I needed,
which is to set variable namespace according to defined config (ini) file
In php, I would make a .ini file and use parse_ini_file() function.
For the worknig perl monitoring script, I used Parse::RecDescent
Anyhow, the main point of this follow up is a basic example for the
future if someone else runs into the same issues I did (Python's
documentation is not well written at all, and difficult to use)
>
> !DSPAM:44aac00477171290140515!
>
>
More information about the Tutor
mailing list