Разделение данных конфигурации и логики сценария в сценариях Perl

Я нахожу следующий антишаблон повторенным в моих сценариях Perl: сценарий содержит некоторую машину/установку определенные настройки, которые я храню встроенный как константы в сценарии, тогда как остальная часть сценария носит общий характер:

#!/usr/bin/perl

use strict;
use warnings;

# machine specific settings at the start of the script.
my $SETTING_1 = "foo";
my @SETTING_2 = ("123", "456");
my $SETTING_3 = "something";

# general part of script follows.
...

Этот шаблон несколько хорошо при работе одной машины, но как только я хочу распределить сценарий нескольким машинам, проблема запускается, так как я должен отслеживать так, чтобы я не перезаписывал настройки, расстаются с новыми обновлениями в общей части.

Правильное решение состоит в том, чтобы, очевидно, иметь один общий файл сценария и иметь его, считал конфигурационный файл, который характерен для среды, в которой работает сценарий.

Мой вопрос: Какой модуль CPAN Вы рекомендовали бы для решения этой проблемы? Почему?

9
задан knorv 4 March 2010 в 18:00
поделиться

8 ответов

Мне больше всего нравится Config :: Std . Мне нравится, как он обрабатывает многострочные и многострочные значения конфигурации.

Будьте осторожны, когда переменная потенциально многозначная: если в файле конфигурации существует одно значение, оно сохранит значение в скаляре; если существует несколько значений, вы получите ссылку на массив.

Я считаю удобным иметь два файла конфигурации: один для значений, описывающих операционную среду (где искать библиотеки и т. Д.), А другой для поведения, изменяемого пользователем.

Я также люблю писать вокруг него оболочку. Например (обновлено, чтобы включить автоматически сгенерированные средства доступа только для чтения):

#!/usr/bin/perl

package My::Config;
use strict; use warnings;

use Config::Std;
use FindBin qw($Bin);
use File::Spec::Functions qw( catfile );

sub new {
    my $class = shift;
    my ($config_file) = @_;

    $config_file = catfile($Bin, 'config.ini');
    read_config $config_file => my %config;

    my $object = bless \%config => $class;

    $object->gen_accessors(
        single => {
            install => [ qw( root ) ],
        },
        multi => {
            template => [ qw( dir ) ],
        },
    );

    return $object;
}

sub gen_accessors {
    my $config = shift;
    my %args = @_;

    my $class = ref $config;

    {
        no strict 'refs';
        for my $section ( keys %{ $args{single} } ) {
            my @vars = @{ $args{single}->{$section} };
            for my $var ( @vars ) {
                *{ "${class}::${section}_${var}" } = sub {
                    $config->{$section}{$var};
                };
            }
        }

        for my $section ( keys %{ $args{multi} } ) {
            my @vars = @{ $args{multi}->{$section} };
            for my $var ( @vars ) {
                *{ "${class}::${section}_${var}" } = sub {
                    my $val = $config->{$section}{$var};
                    return [ $val ] unless 'ARRAY' eq ref $val;
                    return $val;
                }
            }
        }
    }

    return;
}

package main;

use strict; use warnings;

my $config = My::Config->new;

use Data::Dumper;
print Dumper($config->install_root, $config->template_dir);
C:\Temp> cat config.ini
[install]
root = c:\opt

[template]
dir = C:\opt\app\tmpl
dir = C:\opt\common\tmpl

Вывод:

C:\Temp> g.pl
$VAR1 = 'c:\\opt';
$VAR2 = [
          'C:\\opt\\app\\tmpl',
          'C:\\opt\\common\\tmpl'
        ];
4
ответ дан 4 December 2019 в 11:41
поделиться

Обычный низкотехнологичный метод - просто выполнить EXPR файл конфигурации. Вы изучали это?

1
ответ дан 4 December 2019 в 11:41
поделиться

Рискуя быть высмеянным вне класса, одно из решений - сохранить конфигурацию в XML (или, для более смелых, JSON). Потребляемый человеком, совместимый за пределами Perl, не обязательно должен находиться на локальном ПК (XML и JSON могут быть запрошены с помощью «URL-адреса конфигурации») и множества стандартных модулей (XML :: Simple обычно достаточно для config XML-файлы) существуют на CPAN.

1
ответ дан 4 December 2019 в 11:41
поделиться

Для простой конфигурации, подобной этой, особенно для тривиальных вещей, когда я не ожидаю, что эти данные изменятся в реальном мире, я часто просто использую YAML. Простота не может быть лучше:

Сначала напишите структуру данных на Perl, содержащую вашу конфигурацию.

use YAML;

my $SETTINGS = {
    '1' => "foo",
    '2' => ["123", "456"],
    '3' => "something",
};

Затем передайте ее в YAML::DumpFile();

YAML::DumpFile("~/.$appname.yaml", $SETTINGS);

Удалите структуру данных и замените ее на

my $SETTINGS = YAML::LoadFile("~/.$appname.yaml");

А затем забудьте о ней. Даже если вы не знаете или не хотите изучать синтаксис YAML, небольшие изменения в конфигурации можно сделать вручную, а более серьезные - на Perl, а затем повторно выгрузить в YAML.

1
ответ дан 4 December 2019 в 11:41
поделиться

Библиотека Config: Properties удобна для чтения и записи файлов свойств пары ключ / значение.

2
ответ дан 4 December 2019 в 11:41
поделиться

Не привязывайте себя к формату - используйте Config :: Any , или, для немного большего фактора DWIM, Config :: JFDI (который сам является оболочкой для Config :: Any). С ними вы покупаете возможность поддерживать INI, YAML, XML, конфигурацию в стиле Apache и многое другое.

Config :: JFDI основывается на этом, пытаясь уловить некоторые из магических свойств загрузчика конфигурации Catalyst: слияние локальной конфигурации экземпляра с конфигурацией всего приложения, поддержка переменных среды и ограниченные возможности макросов ( __ path_to ( foo / bar) __ на удивление часто пригодится.)

0
ответ дан 4 December 2019 в 11:41
поделиться

Для конфигурационных файлов мне нравится использовать YAML. Простой, кроссплатформенный, читаемый человеком, и нет опасности, что ваша конфигурация случайно превратится в настоящую программу.

7
ответ дан 4 December 2019 в 11:41
поделиться

Я предпочитаю YAML и YAML :: XS для данных конфигурации. Он простой, читаемый и привязан практически к любому языку программирования. Другой популярный вариант - Config :: General .

2
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: