207

Perlモジュールが検索される場所に影響を与えるすべての方法は何ですか?または、Perlの@INCはどのように構築されますか?

ご存知のように、Perlは@INCディレクトリ名を含む配列を使用してPerlモジュールファイルを検索する場所を決定します

StackOverflowには包括的な「@INC」FAQタイプの投稿がないようですので、この質問は1つとして意図されています。

4

3 に答える 3

260

この配列の内容がどのように構築され、Perlインタープリターがモジュールファイルを見つける場所に影響を与えるように操作できるかを見ていきます。

  1. デフォルト@INC

    Perlインタープリターは、特定のデフォルト値でコンパイルされ@INCます。この値を見つけるには、env -i perl -Vコマンドを実行し(環境変数をenv -i無視しPERL5LIBます-#2を参照)、出力に次のようなものが表示されます。

    $ env -i perl -V
    ...
    @INC:
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    

.最後に注意してください。これは現在のディレクトリです(必ずしもスクリプトのディレクトリと同じである必要はありません)。Perl 5.26以降、およびPerlが-T(汚染チェックが有効になっている)で実行されている場合は欠落しています。

Perlバイナリコンパイルを設定するときにデフォルトのパスを変更するには、設定オプションを設定しますotherlibdirs

Configure -Dotherlibdirs=/usr/lib/perl5/site_perl/5.16.3

  1. 環境変数PERL5LIB(またはPERLLIB

    Perlは、シェルの環境変数(定義されていない場合は使用)@INCに含まれるディレクトリ(コロンで区切られた)のリストをプリペンドします。afterおよびenvironment変数の内容が有効になったことを確認するには、を実行します。PERL5LIBPERLLIB@INCPERL5LIBPERLLIBperl -V

    $ perl -V
    ...
    %ENV:
      PERL5LIB="/home/myuser/test"
    @INC:
     /home/myuser/test
     /usr/lib/perl5/site_perl/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/site_perl/5.18.0
     /usr/lib/perl5/5.18.0/x86_64-linux-thread-multi-ld
     /usr/lib/perl5/5.18.0
     .
    
  2. -Iコマンドラインオプション

    Perlは、コマンドラインオプション@INCの値として渡されたディレクトリのリスト(コロンで区切られた)をプリペンドします。-Iこれは、Perlオプションで通常行われるように、3つの方法で実行できます。

    • コマンドラインで渡します。

      perl -I /my/moduledir your_script.pl
      
    • Perlスクリプトの最初の行(shebang)を介して渡します。

      #!/usr/local/bin/perl -w -I /my/moduledir
      
    • PERL5OPTそれを(または)環境変数の一部として渡します( PerlPERLOPTのプログラミングの19.02章を参照) 。

  3. プラグマを介して渡しますlib

    @INCPerlは、を介して渡されたディレクトリのリストをプリペンドしuse libます。

    プログラムの場合:

    use lib ("/dir1", "/dir2");
    

    コマンドライン:

    perl -Mlib=/dir1,/dir2
    

    を介してディレクトリを削除する@INCno libこともできます。

  4. @INC通常のPerl配列として直接操作できます。

    注:@INCはコンパイルフェーズで使用されるため、これはステートメントBEGIN {}の前にあるブロック内で実行する必要があります。use MyModule

    • を介して最初にディレクトリを追加しunshift @INC, $dirます。

    • を介して最後にディレクトリを追加しpush @INC, $dirます。

    • Perl配列でできる他のことは何でもしてください。

注:ディレクトリは、この回答にリストされている順序でシフト解除@INCれます。たとえば、デフォルト@INCはリストの最後、前にPERL5LIB、前に-I、前にuse lib、ダイレクト@INCマニピュレーションがあり、後者の2つはPerlコードの順序で混合されます。

参照:

Stack Overflowに関する包括的なFAQタイプの投稿はないようです@INCので、この質問は1つとして意図されています。

それぞれのアプローチをいつ使用するのですか?

  • ディレクトリ内のモジュールをサイトの多くの/すべてのスクリプトで使用する必要がある場合、特に複数のユーザーが実行する必要がある場合は、そのディレクトリを@INCPerlバイナリにコンパイルされたデフォルトに含める必要があります。

  • ディレクトリ内のモジュールが、ユーザーが実行するすべてのスクリプトに対して特定のユーザーによって排他的に使用される場合(または、Perlの再コンパイルが@INC以前の使用例でデフォルトを変更するオプションではない場合)PERL5LIB、通常はユーザーのログイン時にユーザーを設定します。

    注:通常のUnix環境変数の落とし穴に注意してください。たとえば、特定のユーザーとしてスクリプトを実行しても、そのユーザーの環境が設定された状態でスクリプトを実行することは保証されませんsu

  • ディレクトリ内のモジュールを特定の状況でのみ使用する必要がある場合(たとえば、スクリプトが開発/デバッグモードで実行される場合)、PERL5LIB手動で設定するか、-Iオプションをperlに渡すことができます。

  • モジュールを特定のスクリプトにのみ使用する必要がある場合は、モジュールを使用するすべてのユーザーが、プログラム自体でuse lib/ no libpragmasを使用します。また、実行時に検索するディレクトリを動的に決定する必要がある場合にも使用する必要があります。たとえば、スクリプトのコマンドラインパラメータやスクリプトのパスから使用します(非常に優れた使用例については、FindBinモジュールを参照してください)。

  • 複雑なロジックに従ってディレクトリを操作する必要がある場合は、 /プラグマ@INCの組み合わせで実装するには扱いにくいため、ブロック内または操作用に指定された専用ライブラリ内で直接操作を使用します。これはスクリプトで使用する必要があります。 (s)他のモジュールが使用される前。use libno lib@INCBEGIN {}@INC

    この例は、prod / uat / devディレクトリ内のライブラリを自動的に切り替えることです。devやUATから欠落している場合は、prodでウォーターフォールライブラリをピックアップします(最後の条件により、標準の「use lib+FindBin」ソリューションがかなり複雑になります。Aこのシナリオの詳細な説明は、ベータ版Perlスクリプトからベータ版Perlモジュールを使用するにはどうすればよいですか?にあります。

  • 直接操作するための追加のユースケース@INCは、サブルーチン参照またはオブジェクト参照を追加できるようにすることです(はい、バージニア州では、@ INCのサブルーチン参照はいつ呼び出されますか?で@INC説明されているように、ディレクトリ名だけでなくカスタムPerlコードを含めることができます)。

于 2010-03-26T21:15:29.393 に答える
20

上記の場所に加えて、OSXバージョンのPerlにはさらに2つの方法があります。

  1. /Library/Perl/x.xx/AppendToPathファイル。このファイルにリストされているパスは、実行時に@INCに追加されます。

  2. /Library/Perl/x.xx/PrependToPathファイル。このファイルにリストされているパスは、実行時に@INCの前に付加されます。

于 2012-07-31T00:07:39.670 に答える
7

すでに述べたように、@ INCは配列であり、必要なものを自由に追加できます。

私のCGIRESTスクリプトは次のようになります。

#!/usr/bin/perl
use strict;
use warnings;
BEGIN {
    push @INC, 'fully_qualified_path_to_module_wiht_our_REST.pm';
}
use Modules::Rest;
gone(@_);

なくなったサブルーチンはRest.pmによってエクスポートされます。

于 2013-05-04T22:16:19.717 に答える