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

Hi,

I'm having problems by reading hash variables from "config" files ...

I have this in test.conf file :
%Log_rooms = ( "gallery" => { 'BM_shutts_south_00' => 1, 'BM_shutt_no +rth_00' => 1 } );

then I have Cybro_Items.pm:
my $config_file ="/etc/test.conf"; my %Log_rooms; t if (-e $config_file) { print "Reading Configuration from $config_file \n\n"; my $return = do $config_file ; warn "couldn't parse $config_file: $@" if $@; warn "couldn't do $config_file: $!" unless defined $return; warn "couldn't run $config_file" unless $return; } else { print "Using Default Configuration \n\n"; t %Log_rooms = ( "default" => { 'BM_shutts_south_00' => 1, 'BM_ +shutt_north_00' => 1 }, ); ... package Cybro_Item; ... sub get_extra_rooms_for_log { my($self,$var_name) = @_; my %match=undef; while(($room, $room_hash) = each(%Log_rooms)) { ...

if config file doesn't exist, everything works ok with predefined default variable content. If config file exists, then %Log_rooms is empty...

What do I have to put into test.conf file or how to read it in right way, so I could get variable content either from default settings or configuration file... I guess I also have some mistakes on how to deal with variables in such situation. I'd like to have %Log_rooms as global variable, visible from everywhere - let me stress that Cybro_Item package is used in another main test.pl program as :
use Cybro_Items;
I'd kindly ask for some help,

thanks in advance,

regards,

Bulek.

Replies are listed 'Best First'.
Re: Cannot read hash variable from file as global...
by CountZero (Bishop) on Mar 27, 2009 at 06:57 UTC
    If %Log_rooms has to be global then don't declare it as a lexical (my) variable. That makes it effectively not-existing outside its lexical scope.

    Dropping the "my" makes this variable "global" in its package, which I assume to be the "main" package for lack of another package declaration, so to access the %Log_rooms on another package, you have to access it as %main::Log_rooms.

    %Log_rooms = (one => 1, two => 2, three => 3); # we are in the "main" +package here package Cybro_Item; print join "\n", keys %main::Log_rooms;

    PS: There are better ways of dealing with config-files. Personally I am very fond of the family of YAML modules.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Hi,

      thanks for help. I must be really Perl dumb, it still doesn't work for me. I'd kindly ask for some more help.

      If I put your code in Cybro_Items.pm and would like to read %Log_rooms from external file only if it exists and then use Cybro_Items.pm in other main program (for instance test.pl - with "use Cybro_Items;" in it) - what modifications are necessary ?

      1. what do I have to change in this case ? In what scope is then %Log_rooms ?

      2. can I access content of variable also with $main::Log_rooms{one} ?

      Again sorry for dummy questions,

      thanks in advance,

      Bulek.

        (Just to get this out of the way first: I agree with CountZero and the previous Anonymous answerer that you should consider another way to deal with config files.)

        Back up a bit. Understand that your do(), if successful, puts the last expression in $config_file into the variable $return, but you're throwing that value away in your code!

        This is how I'd go about it:

        First, format your config file as a single hash reference expression like this:

        { default => { 'BM_shutts_south_00' => 1, 'BM_shutt_north_00' => 1, }, };

        I just used your defaults above, so update as necessary.

        To read the config file:

        # define %Log_rooms out here, where it will remain in scope: my %Log_rooms = ( default => { 'BM_shutts_south_00' => 1, 'BM_shutt_north_00' => 1 } ); my $return = do $config_file; if ($return && UNIVERSAL::isa($return, 'HASH')) { # we got a hash reference back, so override the defaults: %Log_rooms = %$return; } else { # do whatever you need to do to recover warn "Using default values.\n"; }
Re: Cannot read hash variable from file as global...
by Anonymous Monk on Mar 27, 2009 at 03:12 UTC