++ed by:
2 non-PAUSE users
Author image Олег Пронин


Panda::Config::Perl - Convenient and flexible config loader in perl format.



    $db = {
        host     => 'db.myproj.com',
        driver   => 'Pg',
        user     => 'ilya',
        password => 'rumeev',

    $home    = Path::Class::Dir->new('/home/myproj');
    $var_dir = $home->subdir('var');
    $log_dir = $var_dir->subdir('log'); $log_dir->mkpath(0, 0755);

    $host ||= 'mysite.com';
    $uri = URI->new("http://$host");
    #include "chat.conf"


    #namespace chat
    $history_cnt = 10;
    $tmp_dir = $NS::var_dir->subdir('chat');
    $service_uri = URI->new( $NS::uri->as_string .'/chat' );


    $dev = 1;
    $db->{host} = 'dev.myproj.com';
    $NS::chat::history_cnt += 5;
    ...other differences


    $host = 'dev.mysite.com';
    #include "myapp.conf"
    #include "myapp.dev.conf";

in application:

    my $cfg = Panda::Config::Perl->process('myapp.conf');
    print $cfg->{db}{user}; # ilya
    print $cfg->{db}{host}; # db.myproj.com
    print $cfg->{chat}{tmp_dir}; # Path::Class::Dir object (/home/myproj/var/chat)
    print $cfg->{host}; # mysite.com
    print $cfg->{uri}; # URI object http://mysite.com
    print $cfg->{chat}{service_uri}; # URI object (http://mysite.com/chat)

    $cfg = Panda::Config::Perl->process('local.conf', {hello => 'world'});
    print $cfg->{db}{user}; # ilya
    print $cfg->{db}{host}; # dev.myproj.com
    print $cfg->{host}; # dev.mysite.com
    print $cfg->{uri}; # URI object http://dev.mysite.com
    print $cfg->{chat}{service_uri}; # URI object http://dev.mysite.com/chat
    print $cfg->{chat}{history_cnt}; # 15
    print $cfg->{hello}; # world


This module provides you with powerful config system.

It allows you to:

  • Write variable definitions in perl language. You do not need to define a huge hash in config file - you just write separate variables.

        $var = 'value';
        $arr = [1..100];

    These variables are accessible in config hash by name.

        $cfg = Panda::Config::Perl->process(...);
        say length @{$cfg->{arr}};
  • Split your configs into separate files and include them.

        #include "something.conf"
        #include $filename . ".conf"
        if ($something) {
            #include "something.conf"
  • Access variables between configs.

        $myvar = $NS::var + 10; # access variable 'var' from root namespace
  • Overwrite variables from another config file. Just change their values.


    If both destination and source are hashrefs, they are merged

        $NS::somehash = {a => 1};
        $NS::somehash = {key => $NS::somehash->{a}};
        exists $cfg->{somehash}{a}; # true
        exists $cfg->{somehash}{key}; # true
  • Use namespaces.

        #namespace jopa
        $var = 10;

    Everything under namespace jopa goes to $cfg->{jopa}{...}

This is very useful for big projects where your config might grow over 100kb.


Syntax is quite simple - it's perl. Just define variable with desired names.

$var_name = 'value';

Values can be any that scalars can be: scalar, hashref, arrayref, subroute, etc. DO NOT write use strict or you will be forced to define variables via our which is ugly for config.

If you define in myapp.conf (root config)

    $welcome_msg = 'hello world';

it will be accessible via


Hashes acts as they are expected:

    $msgs = {
        welcome => 'hello world',
        bye     => 'bye world',


It is a good idea to reuse variables in config to allow real flexibility:

    $var_dir = $home->subdir('var');
    $log_dir = $var_dir->subdir('log');
    $chat_log_dir = $log_dir->subdir('chat');

In contrast to:

    $var_dir = 'var';
    $log_dir = 'log';
    $chat_log_dir = 'chat';


    $var_dir = 'var';
    $log_dir = 'var/log';
    $chat_log_dir = 'var/log/chat';
    ...will grow :(

The second and third examples are much less flexible. By means of second example we just hardcoded a part of config logic in our application: it supposes that var_dir is UNDER home and log_dir is UNDER var_dir, etc, which must not be an application's headache anyway. In third example we have a lot of copy-paste and application still supposes that var_dir is under home.


Initial config file (that one which was passed to process method) evaluated in root namespace. That means that all variables appears on the first level in $cfg hash.

If you define a namespace then everything in that namespace goes under namespace key in $cfg. You can change namespaces as many times as you like. Every namespace definition doesn't depend on namespace it defined in, and starts a namespace from current file's root namespace (which is a real root namespace in initial file).


    $var = 10; # root namespace, $cfg->{var}
    #namespace ns1
    $var = 20; # $cfg->{ns1}{var}

    #namespace ns1::subns
    $var = 20; # $cfg->{ns1}{subns}{var}
    #namespace ns2
    $var = 30; # $cfg->{ns2}{var}
        #namespace ns3
        $var = 40; # $cfg->{ns3}{var}
    $var2 = 50; # $cfg->{ns2}{var2}, because the last namespace in scope (#namespace ns2) is still in effect
    $var2 = 60; # $cfg->{var2}, because '#namespace' without a name reverts to the local root namespace

When you include a file it inherits current namespace and it becomes that file's local root namespace. It means that all namespaces that file defines are added to it's local root namespace.


    #namespace abc
    #include "my.conf"


    $var = 10; # $cfg->{abc}{var}
    #namespace def
    $var = 20; # $cfg->{abc}{def}{var}
    #namespace xyz
    $var = 30; # $cfg->{abc}{xyz}{var}
    $str = 'asd'; # $cfg->{abc}{str}
    #namespace-abs hi
    $str = 'ttt'; # $cfg->{hi}{str}
    $str = 'yyy'; # $cfg->{str}

As you can see, #namespace-abs defines a namespace which always starts from a real root namespace regardless of what local root namespace is set to.

Namespace name must be a literal string, variables and expressions are not supported.


You can include another config file by saying

    #include "path/to/file.conf"

As you could see in NAMESPACES section, included file inherits current visible namespace as local root namespace. The path to config file can either be an absolute path, starting with '/' or path relative to including config file (not a current working dir!).

You can use any perl-valid expression as a filename


To access variable var which is in root namespace, use


To access variable var which is in namespace xxx::yyy, use


$NS stands for NameSpace root.


When you change some hash contents (for example from a file which is conditionally included), instead of writing

    $NS::db->{host} = 'another.host.com';
    $NS::db->{user} = 'another_user';
    $NS::db->{password} = 'otherpass';

You can write

    $NS::db = {
        host => 'another.host.com',
        user => 'another_user',
        password => 'otherpass',

All assigment operations in config files merge hashrefs if both left and right operands are hashrefs. Merge is done by Data::Recursive's merge function with default flags, which does hash merging extremely fast.

If you really need to completely overwrite an existing hashref with a new value, use list assigment operator, because merging is only done for OP_SASSIGN, not for OP_AASSIGN.

    ($NS::db) = { ... };


process ($file, \%initial_cfg)

Processes config $file and returns the result as a hashref.

initial_cfg is a set of predefined variables which will appear in root namespace just before processing config. You can predefine variables in an arbitrary namespace using keys ending with '::', for example:

    Panda::Config::Perl->process($file, {
        var => 'str',
        'MyNS::' => { num => 10, 'SubNS::' => { array => [1,2,3] } },
        'OtherNS::SubNS::' => { hash => {} },


    It takes about 7ms to process config tree with 30 files of summary size 220kb on Core i7 3930K.


This module deprecates Catalyst::Plugin::ConfigLoader::MultiState


Pronin Oleg <syber@cpan.org>, Crazy Panda, CP Decision LTD


You may distribute this code under the same terms as Perl itself.