9

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.
...

このパターンは、1 台のマシンで実行する場合は多少問題ありませんが、スクリプトを複数のマシンに配布したい場合は、一般的な部分の新しい更新プログラムで設定部分を上書きしないように追跡する必要があるため、すぐに問題が発生します。

正しい解決策は明らかに、一般的なスクリプト ファイルを 1 つ用意し、スクリプトが実行される環境に固有の構成ファイルを読み取るようにすることです。

私の質問は次のとおりです。この問題を解決するために、どの CPAN モジュールをお勧めしますか? なんで?

4

8 に答える 8

7

構成ファイルには、 YAMLを使用するのが好きです。シンプルで、クロスプラットフォームで、人間が読める形式であり、構成が誤って実際のプログラムに変形する危険がありません。

于 2010-03-04T17:59:44.933 に答える
4

私のお気に入りはConfig::Stdです。複数行および複数部分の構成値を処理する方法が気に入っています。

変数が複数の値を持つ可能性がある場合は注意が必要です。構成ファイルに単一の値が存在する場合、その値はスカラーに格納されます。複数の値が存在する場合は、配列参照を取得します。

2 つの構成ファイルがあると便利だと思います。1 つは動作環境 (ライブラリの場所など) を記述する値用で、もう 1 つはユーザーが変更可能な動作用です。

また、その周りにラッパーを書くのも好きです。例 (自動生成された読み取り専用アクセサーを含むように更新):

#!/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> 猫 config.ini
[インストール]
ルート = c:\opt

[テンプレート]
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'
        ];
于 2010-03-04T18:33:12.620 に答える
2

Config:Propertiesライブラリは、キーと値のペアのプロパティ ファイルの読み取りと書き込みに適しています。

于 2010-03-04T18:05:51.517 に答える
2

構成データにはYAMLYAML::XSを好みます。シンプルで読みやすく、ほぼすべてのプログラミング言語に対応しています。別の一般的な選択肢はConfig::Generalです。

于 2010-03-04T17:58:41.597 に答える
1

クラス外で笑い飛ばされるリスクがあるため、解決策の 1 つは構成を XML (より冒険的な場合は JSON) に保存することです。人間が消費でき、Perl の外部で相互運用可能であり、ローカル PC (XML と JSON の両方を「構成 URL」から要求できます) と多数の標準モジュール (通常は XML::Simple で十分です) に常駐する必要はありません。 config XML ファイル) が CPAN に存在します。

于 2010-03-05T00:14:55.497 に答える
1

通常のローテクな方法は、単純に構成ファイルを EXPRすることです。これを調べましたか?

于 2010-03-04T17:55:31.357 に答える
1

このような単純な構成の場合、特にこのデータが現実の世界で変更されるとは思わない些細なことについては、単純に 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 に再度ダンプすることができます。

于 2010-03-05T13:30:07.600 に答える
0

形式に縛られないでください -- Config::Anyを使用するか、もう少し奇抜な DWIM 要素であるConfig::JFDI (それ自体が Config::Any をラップします) を使用します。それらを使用すると、INI、YAML、XML、 Apache スタイルの configなどをサポートする機能を購入できます。

Config::JFDI は、Catalyst の構成ローダーの魔法の一部を捉えようとすることで、これに基づいて構築されています: インスタンスローカル構成とアプリ全体の構成、環境変数のサポート、および限定されたマクロ機能のマージ (__path_to(foo/bar)__驚くほど頻繁に役立ちます)。

于 2010-03-05T13:11:38.477 に答える