Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Saving application configuration to files

by crabbdean (Pilgrim)
on Mar 29, 2004 at 01:37 UTC ( #340470=perlquestion: print w/ replies, xml ) Need Help??
crabbdean has asked for the wisdom of the Perl Monks concerning the following question:

Hi Fellow Monks,

Simple question really. What is the best module for saving an applications configurations to a text file?

You usually see this is some kind of SystemFile = "this/directory/here" kind of format.

Now I could create my own and could also do it in DBM files if I wanted but I just want a simple text file. I'm sure someone clever has invented this before so I'm sure someone out there also knows about it. Thanks

Dean
The Funkster of Mirth
Programming these days takes more than a lone avenger with a compiler. - sam
RFC1149: A Standard for the Transmission of IP Datagrams on Avian Carriers

Comment on Saving application configuration to files
Download Code
Re: Saving application configuration to files
by kvale (Monsignor) on Mar 29, 2004 at 01:42 UTC
    I have used Config::IniFiles to good effect:
    use Config::IniFiles; my $cfg = new Config::IniFiles( -file => "/path/configfile.ini" ); print "The value is " . $cfg->val( 'Section', 'Parameter' ) . "." if $cfg->val( 'Section', 'Parameter' );

    -Mark

Re: Saving application configuration to files
by exussum0 (Vicar) on Mar 29, 2004 at 01:44 UTC
    You have many ways.

    1. you have your basic properties file. i.e. Something=Something else. You split off the first equals.

    2. You have XML. We can argue that XML is hard to process or is easy to screw up, or not those cases. Not the point. It's viable and apache's httpd server uses it :)

    c. You have ini files.

    There are modules and really simple algorithms to implement any of these. Matter of complexity of your configuration ideas and how much you want users to tamper with them directly.


    -- "So far my experience has been that most people who go for certification have broad but not deep knowledge in the field and the flavor of the knowledge is academic. But every once in a while one finds a gem of a person who learns all the time and uses certification to prove it." -- on Orkut

      Well, httpd uses an XML-like format for its config file, but it's not fair to call it XML. There's no top-level element, attribute values aren't quoted, the comment format is different, and whitespace is sometimes significant. But it's certainly XML- or SGML-inspired.
Re: Saving application configuration to files
by dragonchild (Archbishop) on Mar 29, 2004 at 01:55 UTC
    My favorite is Config::ApacheFormat. I have found it to be the most expressive and the easiest to work with. Plus, since I run web apps, I have to use it anyways. :-)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Saving application configuration to files
by Fletch (Chancellor) on Mar 29, 2004 at 02:36 UTC
Re: Saving application configuration to files
by Anonymous Monk on Mar 29, 2004 at 03:06 UTC

    Here's one really simple way to read in a commonly used config format. This version requires the double quotes around all values. You could modify it to suit your needs (ie: no quotes needed, give warnings/errors if it comes across an invalid config line, etc) but as it is, it works just fine.

    use strict; use warnings; my ($sec, %config); while (<DATA>) { $sec = $1 and next if /^\[([^\]]+)\]/; $config{$sec}{$1} = $2 if /^\s*([^=]+)\s*=\s*"([^"]+)"/; } =cut we now have ths following structure: %config = ( client => { host = 'localhost', port = '8080' }, server => { host => 'localhost', port => '8900', timeout => '60' } ); =cut __DATA__ [client] host="localhost" port="8080" [server] host="localhost" port="8900" timeout="60"
Re: Saving application configuration to files
by b10m (Vicar) on Mar 29, 2004 at 06:32 UTC

    Oh well, most Config modules have been mentioned, so let's add another one: Config::General. I especially like the save_file() function, which makes life too easy ;)

    --
    b10m

    All code is usually tested, but rarely trusted.

      I'll second the vote for Config::General -- I've not tried too many others, but I found it quick and easy to get working (i.e. about two minutes). It's designed to match the apache config format. Options are name/value pairs (equals optional). Also supports blocks (become hashes), named blocks (hashes within hashes), and multiple identical options (arrays), long lines separated with \, here documents, include files, and numerous options to control how these fancy configuration settings are handled (including a default hash). As I said, though, the basic operation is quick and painless.

      Another nice feature is that Config::General has both save_file() and save_string() methods if for some reason you'd like to get the text of the config file and handle file operations yourself (or print to command line for redirection).

      Stealing a page (rather, function) from Config::Auto, I use a routine to search for a config file with a bunch of standard names in a bunch of standard places so it doesn't even have to be entered on the command line or hard-coded. So the following snippet of code is just part of my standard script template now.

      # command line options, including config already gotten from Getopt::L +ong and stored in %opt # procedural approach -- Config::General also has an OO approach $opt{config} ||= find_file(); my %config; %config = ParseConfig(-ConfigFile => $opt{config}, -AutoTrue => 1) if $opt{config}; # find_file copied and modified from a version found in Config::Auto sub find_file { my $x; my $whoami = basename($0); my $bindir = dirname($0); $whoami =~ s/\.pl$//; for ("${whoami}config", ".${whoami}config", "${whoami}.config", ".${whoami}.config", "${whoami}conf", ".${whoami}conf", "${whoami}.conf", ".${whoami}.conf", "${whoami}rc", ".${whoami}rc") { return $_ if -r $_; return $x if -r ($x=catfile($bindir,$_)); return $x if -r ($x=catfile($ENV{HOME},$_)); return $x if -r ($x=catfile(rootdir(),"etc",$_)); } return undef; }

      I thought about releasing the find_file code in a standalone module, but figured I'd see how Config::Auto matured and if it winds up included similar functionality.

      -xdg

      Code posted by xdg on PerlMonks is public domain. It has no warranties, express or implied. Posted code may not have been tested. Use at your own risk.

      DG: edited code example for clarity and elegance

Re: Saving application configuration to files
by maa (Pilgrim) on Mar 29, 2004 at 06:44 UTC

    No-one has mentioned do... perldoc -f do

    You might like to use "do" to read in a program configuration File. Manual error checking can be done this way:
    # read in config files: system first, then user for $file ("/share/prog/defaults.rc", "$ENV{HOME}/.someprogrc") { 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; } }

      I like the idea of using 'do', but I have what's probably a basic mis-understanding on my part.

      Under use strict;, the 'do' executes what's in my configuration file, but I don't understand what happens to my scope. When I'm back in the calling file, I can't see the variable set in the config file. I tried 'package main;' at the top of my config, and it didn't do the trick.

      ######### calling script #!/usr/bin/perl use strict; my $x; my $file = 'my.conf'; unless (my $return = do $file) { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; } print "\$x is $x\n"; ########## config script (my.conf) package main; $x = 'abcdef'; 42;

      Where am I going wrong here?

        It works if you declare your variables using our.

        I've never actually used this method though... see perldoc -f our for info on how it affects scope.

        You can ensure you don't go clobbering things by reassigning the imported values once you get them (if you feel safer)

        #!/usr/bin/perl use strict; our ($x); my $file = 'conf.pl'; unless (my $return = do $file) { warn "couldn't parse $file: $@" if $@; warn "couldn't do $file: $!" unless defined $return; warn "couldn't run $file" unless $return; } print "\$x is $x\n"; my $var_x=$x; ########## config script (my.conf) $x = 'abcdef';

        I suppose the method you are going to use depends on who is going to be editing the config file, doesn't it... if they know perl then any method should be fine. If they don't then a standard INI format or plain assignments might be better.

        HTH - mark

Re: Saving application configuration to files
by skx (Parson) on Mar 29, 2004 at 11:42 UTC

    Several people have already made suggestions, but one option that you might not have considered is to use Data::Dumper.

    This could be used to output a data structure of almost arbitary complexity to a configuration file - and then you could read it back into your script via eval.

    The drawback of many of these configuration suggestions, and this one, is that when you perform a save you are going to trash any comments/changes a user might have manually made.

    Steve
    ---
    steve.org.uk
Re: Saving application configuration to files
by eserte (Deacon) on Mar 29, 2004 at 13:47 UTC
    The nicest config file format is YAML. Unfortunately the perl module YAML.pm has some bugs, but the module should be OK for simpler cases.
      I too love YAML and use YAML.pm often, though I do think I might switch to the inifiles modules when I don't need to serialize Massive Convoluted Datastructures (TM). What are these bugs you speak of? Well, yes, CPAN has a 'bugs' section listed for YAML, though it mostly seems to list things that just aren't implemented yet. Nothing that would reach out and bite you really.
        Look for example at the two items in the "important" section (one of them is mine). These are problematic if you're serializing/deserializing arbitrary data. On the other hand, if zou're just using a configuration file with fixed keys and relatively simple values (with no newlines, for example), then YAML should be fine.
      I personally use yaml for all of my configuration needs these days, and though they tend to be simple, YAML is more than OK. It's straight forward and quite easy to read and write by hand. The perl interface is easy. Everything is easy. Don't think I can recommend it enough.
Re: Saving application configuration to files
by periapt (Hermit) on Mar 29, 2004 at 13:51 UTC
    If your config files are simple, I've found the configkey=configvalue set to be the fastest and simplest to use for my purposes. I have a generic routine that I can include in any program to read a specific config file in any program as follows (based on the routine in the Perl Cookbook). I have tried config files using some of the modules mentioned here and in XML format but, for my purposes, it seemed to make things a little more complex without adding a feature that I need (not that they don't have useful features mind you. Just not one that I need.). One thing I have found very helpful in the scheme below, is that I can specify configurations for a set of programs that together make up a system giving me the option of specifiying common elements and program specific elements. You can also specify more than one section to read options from and it will read them sequentially.

    my $cfg = ReadConfig("./configfilename",qw(someprog02)) ############################################################; sub ReadConfig{ # ReadConfig([full path & filename],[section list]) # this subroutine reads a configuration file and returning a # reference to a hash containing the key value pairs. The # routine will use a full path name if provided or look in # the current directory for the configuration file. The # routine will parse all options or just the options provided # in the section parameter. By default, it will include any # value in the [ALL] section if one is existing. The config # reader will process each section in the file in the order # passed to it by the list section. By default, [ALL] will # be processed first and need not be included in the list # unless you want [ALL] to be after some other section. The # routine will overwrite any options set in previous sections # will the option for the current section so that an option # for pgmdir in the section [someprog01] will overlay the # pgmdir option set in the [ALL] section (assuming the [ALL] # section precedes [someprog01] in the config file Note, this # reader will capitalize all section headers so case does not # matter my $infile = shift; my @sect = @_; my %config = (); my %tmpcfg = (); my $line = ''; my $valkey = ''; my $value = ''; my $sectkey = 'ALL'; if(-e $infile and open(INFILE, "<$infile")){ while($line = <INFILE>){ chomp($line); $line =~ s/#.*//; #ignore comments $line =~ s/^\s+//; #delete leading whitespace $line =~ s/\s+$//; #delete trailing whitespace #skip it nothing is left next unless length($line); if($line =~ m/[[](\w+)[\]]/x){ $sectkey = lc($1); }else{ ($valkey,$value) = split(/\s*=\s*/,$line,2) ; $tmpcfg{$sectkey}{lc($valkey)} = $value; } } } unshift @sect, 'ALL'; # prepend 'ALL' section foreach $sectkey (map { lc } @sect){ $config{$_} = $tmpcfg{$sectkey}{$_} foreach (sort keys %{$tmpc +fg{$sectkey}}); } return (%config) ? \%config : '' ; } #end ReadConfig(); ############################################################; __CONFIGFILE__ # test configuration # # this is the configuration file for the SOMESYS processing # system directory entries are relative to basedir unless # otherwise specified # [all] baseshare=\\UNCDRIVE\DATA\ # basedir=K:\DataDrive\Development\rel-2_6\ [someprog01] [someprog02] workdir=ftpbakprocessing\ seplenopts=0,1,2 reclenopts=770,364,750,344 filelenopts=0,1,2 [someprog03] [end]

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://340470]
Approved by exussum0
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (7)
As of 2014-08-21 10:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (133 votes), past polls