toma has asked for the wisdom of the Perl Monks concerning the following question:

I am writing a Tk program that allows users to save various options, such as colors in the GUI and paths for stored files. I would like these options to be restored when the user runs the program again. So I need a persistence mechanism for the options, perhaps like an old-fashioned options .Xdefaults file. I'm guessing that the .Xdefaults file format is now less popular than it once was.

What is the preferred way to store these options?

So far I am considering Data::Denter, Data::Dumper, Storable, XML, and .Xdefaults formats. I could use one of these file formats to store a hash that holds all the option information.

I would like to hear opinions on the best way to do this, and what CPAN modules provide easy-to-implement support for remembering user configuration information.

It should work perfectly the first time! - toma

Replies are listed 'Best First'.
Re: Persistence for options?
by mirod (Canon) on Aug 15, 2001 at 19:43 UTC

    Hey, nice can of worms you opened here toma!

    So here is a summary of what we've got so far. Let me know if you feel like adding more module/options or other fields:

    Module Format In core Notes
    Storable binary X fast
    Data::Dumper text X widely used, need to eval the output to reload it
    Data::Denter text   plug-in replacement for Data::Dumper
    XML::Simple XML    
    Data::DumpXML XML   more complete than XML::Dumper
    XML::Dumper XML   simpler than Data::DumpXML
    hash tied to a DB_File binary X  
    AnyData various   can use CSV, XML, .INI...
    DBD::AnyData various   same as AnyData with a DBI interface
    Tk::Style XML   not on CPAN, for TK stylesheets
    AppConfig text   configuration files can be overridden by command line arguments
    Config::IniFiles text   MS-Windows style .ini files
    Inifile text   MS-Windows style .ini files
    Boulder text, XML   boulder format, plus various bio*-related formats

    Update: added Boulder as suggested below.

      Nice comparison! And yeah, why not add Boulder by Lincoln Stein.

      Update: Boulder is a data format used internally in CGI.pm's query persistence. Here's an excerpt from perldoc CGI.

      =head2 SAVING THE STATE OF THE SCRIPT TO A FILE: $query->save(FILEHANDLE) This will write the current state of the form to the provided filehandle. You can read it back in by providing a filehandle to the new() method. Note that the filehandle can be a file, a pipe, or whatever! The file format used for save/restore is identical to that used by the Whitehead Genome Center's data exchange format "Boulderio", and can be manipulated and even databased using Boulderio utilities. See http://stein.cshl.org/boulder/ for further details.
      --
      Tatsuhiko Miyagawa
      miyagawa@cpan.org

      FWIW, I posted Data::PropertyList to CPAN a couple of years ago, which supports the "property list" format for configuration data originally used by NeXT.

      It's a text format with support for nested data structures, designed to be human-editable, and does not use evals, which puts it somewhere between Data::Denter and Inifile in terms of flexibility.

      Apple has switched to using an XML encoding for these data structures in MacOS X, so this file format is probably only of historical interest at this point...

        Actually, WindowMaker uses the property list format for it's menus and other files.
      Parse::RecDescent is quite capable of reading any kind of configuration file. In fact, you could write a configuration file manager, using other modules to write the config files. That might be cool. And slow.
Re: Persistence for options?
by mirod (Canon) on Aug 15, 2001 at 12:38 UTC

    If you choose XML you can either use XML::Simple (just make sure you read the docs carefully, simple can be a deceptive name ;-), or Data::DumpXML, which is very convenient too.

    Going the pure-Perl way I would tend to use Data::Denter which I find to be easier to read than Data::Dumper and more convenient, as you don't have to eval the saved data, but just use undent.

    If you are looking for speed then Storable is most likely to be the fastest though.

    And note that none of these methods can store code references (subs).

Re: Persistence for options?
by physi (Friar) on Aug 15, 2001 at 11:33 UTC
    Why not tie your option hash to a DB_File ?
    use DB_File; tie %hash, "DB_File", $filename or die "NO DIE\n"; %hash{key}='value'; untie %hash;
    This should create a file $filename and stores all the hash inside. When your program is ended this file will survive and will again be read by the next start of your program.
    ----------------------------------- --the good, the bad and the physi-- -----------------------------------

      Binary config files are evil. Somebody with more experience told me that even Unix used once binary config files (like, for example, sendmail still seems to do and the mailman program (written in Python) does), and it opens a whole can of worms, like version dependencies, platform dependencies and general unmodifiability of the config file if the program used to create it dosen't start anymore.

      Just imagine a version of Perl linked to another (version of) Berkeley DB, or that you want to transfer your config files between machines with different endianness, or between Windows and Unix, where all the path names change.

      Or imagine the hell if the program crashes while writing the configuration file, and won't start up anymore, because the config file is broken, and you have no easy way to tell if the file is complete, and no easy way to fix/salvage the current configuration or what's left of it...

        If you don't trust binary files then maybe a better way will be, to use DBI and CSV like that:
        tie %line, 'Tie::RDBM', "CSV:f_dir=/whatever/log", {table => 'anyfilen +ame', create => 1} or die "no tie $!\n";
        Then you get a human readable file, which is editable.
        ----------------------------------- --the good, the bad and the physi-- -----------------------------------
Re: Persistence for options?
by miyagawa (Chaplain) on Aug 15, 2001 at 09:50 UTC
Re: Persistence for options?
by mattr (Curate) on Aug 15, 2001 at 15:16 UTC
    I wrote code for an INI-like file format, not liking what was available, but now there's DBD::RAM which supports INI format. The good thing is it lets your users edit the file, and it does lend itself to simple hashes. But if you actually would rather not make the file user-editable, tied hash or Storable seem fine.. XML seems like a bit much to me, and a little dangerous (users might think they can edit it without keeping strictly to the rules) but some people might think differently.

    You could also just do an eval on the file in which case it could hold code itself too but most people don't do that (I think Larry Wall did once though).

    Finally DBD::RAM can freeze/thaw data structures:

    DBD:RAM can import data directly from references to arrays of arrayrefs and references to arrays of hashrefs. This allows you to easily import data from some other portion of a perl script into a database format and either save it to disk or simply manipulate it in memory.
(bbfu) (Tk persistance) Re: Persistence for options?
by bbfu (Curate) on Aug 15, 2001 at 18:31 UTC

    You might want to check out Petruchio's Tk::Style. It uses XML::Parser to store Tk widget options... And does pretty much all the work of getting those options to the proper widgets for you. I'm sure you could figure out a way to also add in miscellaneous other options (ie, file paths) in the same file.

    bbfu
    Seasons don't fear The Reaper.
    Nor do the wind, the sun, and the rain.
    We can be like they are.

Re: Persistence for options?
by larryk (Friar) on Aug 15, 2001 at 16:04 UTC
    Never used it but Inifile (Albert K. T. Hui) from CPAN looks like a good bet.
       larryk                                          
    perl -le "s,,reverse killer,e,y,rifle,lycra,,print"
Re: Persistence for options?
by wardk (Deacon) on Aug 15, 2001 at 19:07 UTC

    Two possibilites are AppConfig and Config::IniFiles

    Config::Inifiles supports tying/persistance, cannot vouch for AppConfig.

Re: Persistence for options?
by perrin (Chancellor) on Aug 15, 2001 at 18:38 UTC
    You're making this much harder than it needs to be. If no one needs to edit the file by hand, just use Storable. It has built-in functions for saving and loading a hash from a file, and you can nest data structures inside it if you need to.

    If people need to be able to vi the file, use Andy Wardley's nice AppConfig module. It can merge in overrides from the command line, handle site-wide configs, etc.

Re: Persistence for options?
by jlf (Scribe) on Aug 16, 2001 at 03:08 UTC
    Hello! I am just learning Perl myself, but I recently ran across a module that might be a good fit: Damian Conway's Inline::Files. It generalizes the __DATA__ construct and allows to you have an arbitrary number of "files" inline with your code -- and if the user has write permission to the program, these datahandles can be opened for read/write access too. So you could create an __OPTIONS__ section with default values, and replace them as desired. Check Damian's diary entry for May 26th here for more info.