8.16. Reading Configuration FilesProblemYou want to allow the users of your program to change its behavior through configuration files. SolutionEither process a file in trivial VAR=VALUE format, setting a hash key-value pair for each setting: while (<CONFIG>) { chomp; # no newline s/#.*//; # no comments s/^\s+//; # no leading white s/\s+$//; # no trailing white next unless length; # anything left? my ($var, $value) = split(/\s*=\s*/, $_, 2); $User_Preferences{$var} = $value; } Or better yet, treat the config file as full Perl code: do "$ENV{HOME}/.progrc"; DiscussionThe first solution lets you read in config files in a trivial format like this (comments and blank lines are allowed): # set class C net NETMASK = 255.255.255.0 MTU = 296 DEVICE = cua1 RATE = 115200 MODE = adaptive
After you're done, you can pull in a setting by something like no strict 'refs'; $$var = $value;
and the
The second solution uses # set class C net $NETMASK = '255.255.255.0'; $MTU = 0x128; # Brent, please turn on the modem $DEVICE = 'cua1'; $RATE = 115_200; $MODE = 'adaptive'; If you don't see the point of having extra punctuation and live code, consider this: you can have all of Perl at your disposal. You can now add arbitrary logic and tests to your simple assignments: if ($DEVICE =~ /1$/) { $RATE = 28_800; } else { $RATE = 115_200; } Many programs support system and personal configuration files. If you want the user's choices to override the system ones, load the user file second: $APPDFLT = "/usr/local/share/myprog"; do "$APPDFLT/sysconfig.pl"; do "$ENV{HOME}/.myprogrc";
If you want to ignore the system config file when the user has their own, test the return value of the do "$ENV{HOME}/.myprogrc"; or do "$APPDFLT/sysconfig.pl"
You might wonder what context those files will be executed under. They will be in the same package that
{ package Settings; do "$ENV{HOME}/.myprogrc" }
As with a file read in using
If you don't want clean partitioning of variable visibility, you can get the config file's code executed in your own lexical scope. If you have a eval `cat $ENV{HOME}/.myprogrc`; We've never actually seen anyone (except Larry) use that approach in production code.
For one thing, You can still check for errors on your own if you'd like: $file = "someprog.pl"; unless ($return = do $file) { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; } This is much simpler for the programmer to source in code than it would be to invent and then parse a complicated, new syntax. It's also much easier on the user than forcing them to learn the syntax rules of yet another configuration file. Even better, you give the user access to a powerful algorithmic programming language. One reasonable concern is security. How do you know that the file hasn't been tampered with by someone other than the user? The traditional approach here is to do nothing, trusting the directory and file permissions. Nine times out of ten, this is also the right approach. Most projects just aren't worth being that paranoid over. For those that are, see the next recipe. See Also
The Copyright © 2002 O'Reilly & Associates. All rights reserved. |
|