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

Hello fellow monks. I'm wondering what you think is the best way to keep several variables and constants in one (config-)file to be used by different scripts. Before I used "use strict" and "my $var;" it was no problem. Simply a "require 'myconf.pm';" And I had all my vars ready. So how would you handle these:
my $CONNECT ='DBI:mysql'; my $DB ='SUN'; my $KEYFILE ='key.csv'; my @FILES = <*.csv>;
which have to be used in at least 2 scripts?

Replies are listed 'Best First'.
Re: variables / consts for different scripts
by Abigail-II (Bishop) on Aug 28, 2003 at 07:43 UTC
    package My::Constants; use strict; use warnings; use Exporter; our (@ISA, @EXPORT); @ISA = qw /Exporter/; @EXPORT = qw /$CONNECT $DB $KEYFILES @FILES/; our $CONNECT = 'DBI:mysql'; our $DB = 'SUN'; our $KEYFILE = 'key.csv'; our @FILES = '<*.csv>'; 1;

    And then in your scripts, you'd do use My::Constants.

    Be aware, the code above is untested.

    Abigail

      Sorry, but it didn't work.

      I read perldoc perlmod and from that everything in your example seems okay, except that I used Constants instead of My::Constants.

      I tried perl -e 'use strict; use Constants; print $DB' and get an "Global symbol "$DB" requires explicit package name at -e line 1" :-(

      I'm using perl 5.8.0

      I found my mistake. Your example is perfectly right and I shouldn't use "My::Constants" in the package name when I name it "Constants" everywhere else.

      Thanks for your help!

Re: variables / consts for different scripts
by dragonchild (Archbishop) on Aug 28, 2003 at 12:56 UTC
    My suggestion would be to break this out into 2-3 different modules, each of which would be used by the scripts that need that functionality. Right now, it looks like you have two different functionalities - database connectivity and filelists. So, I would do something like:
    # In file Database.pm package Database; our @ISA = qw(Exporter); our @EXPORT_OK = qw( DB_connect DB_disconnect ); use DBI; my %config = ( type => 'mysql', name => 'SUN', ); sub DB_connect { # Allow the user to override anything they want to in %config %config = (%config, @_); my $connect_string = join(':', 'DBI', $config{type}, $config{name}, ); my $dbh = DBI->connect( $connect_string, $config{user}, $config{password}, $config{options}, ); unless ($dbh) { die "Cannot open connection to $connect_string with $config{us +er} / $config{password}\n" . DBI->errstr, $/; } return $dbh; } sub DB_disconnect { my ($dbh) = @_; $dbh->disconnect if UNIVERSAL::isa($dbh, 'DBI'); return 1; } 1;

    You can do something similar with your files. Now, you have connecting to a database abstracted out into something you can reuse.

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

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Nice idea but not what I needed.

      The files (2 files now) I needed are for

      • configuration settings like DB name, Files for input etc.
      • functions needed in both my scripts
      The task I have to solve with my first script is to read in some "CSV" files and put the data into a (mySQL) DB.

      The other task is just for creating all the "create table" statements needed to set up the database.

      Your suggestion for letting the user override any default I set in my script is okay for something someone might build upon. But as this script will run unatend (sooner or later), there is nothing to override after setting it up once. The variables module is intended for this setup.

        You're missing the point. When you have to write another script that deals with connecting to this MySQL database, but does not have to deal with the CSV files, then you can just use the database connectivity code without having to deal with the overhead of the CSV stuff. Your other task is the perfect example of this. You simply use the DB connectivity code cause that's all you need.

        As for "letting the user override" stuff ... YOU are the user of the module. The module doesn't know, nor care, about your end users. Maybe I should've used the term "client" or "caller", instead.

        The functions you need in both scripts should also be broken about into functional areas. Think about this not in terms of your current task, but in terms of tasks you don't know about yet.

        Here's another spin on it - why do we organize our kitchens? I mean, we're done with the task at hand, which is making today's dinner. Why put the silverware in one drawer and the dishes in another and the pots in a cupboard? Because - being organized and having functional areas defined makes things easier the next time.

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

        The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: variables / consts for different scripts
by wirrwarr (Monk) on Aug 28, 2003 at 09:08 UTC
    I like use constant NAME => 'VALUE';, but this probably doesn't work well with <*.csv>.


    daniel.
      I thought I like it too.

      But then I found out that it is too complicated to use those constants.

      • They won't interpolate into strings leading to
        print "The file '".FILENAME."' cant't be read";
        instead of
        print "The file '$FILENAME' can't be read";
      • I couldn't find out how to (elegantly) use constants in REs. /IDRE=VALRE/ won't work whereas /$IDRE=$VALRE/o isn't a problem