1. ホーム
  2. パール

[解決済み】Perlの@INCはどのように構築されているのでしょうか?(別名、Perlモジュールが検索される場所に影響を与えるすべての方法は何ですか?)

2022-04-14 14:18:03

質問

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

ご存知の通りです。 Perlでは @INC ディレクトリ名を含む配列で、Perlモジュールファイルの検索場所を決定します。 .

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

解決方法を教えてください。

この配列の内容がどのように構築され、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 に含まれるディレクトリのリスト(コロンで区切られたもの)を指定します。 PERL5LIB (定義されていない場合。 PERLLIB が使用されます)シェルの環境変数を使用します。の中身を見るには @INC の後に PERL5LIBPERLLIB を実行すると、環境変数が有効になります。 perl -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 (または PERLOPT )環境変数(19.02章参照) Perlのプログラミング )

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

    Perlのプリペンド @INC を介して渡されたディレクトリのリストで use lib .

    プログラムでは

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

    コマンドラインでは

    perl -Mlib=/dir1,/dir2
    
    

    また からディレクトリを削除します。 @INC を経由して no lib .

  4. を直接操作することができます。 @INC を通常のPerlの配列として使用することができます。

    @INC はコンパイル時に使用されるので、これは BEGIN {} ブロックの前にある use MyModule ステートメントを使用します。

    • を介して、先頭にディレクトリを追加します。 unshift @INC, $dir .

    • を経由して末尾にディレクトリを追加します。 push @INC, $dir .

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

注)ディレクトリは 非シフト 上に @INC を、この回答にある順序で、例えば、デフォルトの @INC はリストの最後にあり、その前に PERL5LIB の前にある。 -I が先行する。 use lib と直接 @INC の操作で、後者の2つはPerlのコードではどのような順番で混在しています。

参考文献

包括的な @INC Stack OverflowにFAQ的な投稿があるので、この質問はその1つとして意図しています。

各アプローチを使用するタイミングは?

  • あるディレクトリにあるモジュールをサイト上の多くの/すべてのスクリプトで使用する必要がある場合、特に複数のユーザーによって実行される場合、そのディレクトリをデフォルトの @INC をPerlバイナリにコンパイルしてください。

  • ディレクトリ内のモジュールが、特定のユーザが実行するすべてのスクリプトに排他的に使用される場合 (または、Perl の再コンパイルが、デフォルトの @INC を設定します。 PERL5LIB 通常、ユーザーのログイン時に行われます。

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

  • ディレクトリ内のモジュールを特定の状況でのみ使用する必要がある場合 (例: スクリプトを開発/デバッグモードで実行する場合) は、以下のように PERL5LIB を手動で渡すか、あるいは -I オプションを perl に追加してください。

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

  • のディレクトリが @INC を組み合わせて実装することが不可能であったり、扱いにくかったりする、複雑なロジックに従って操作する必要があります。 use lib / no lib プラグマを使用する場合は、直接 @INC の中で操作します。 BEGIN {} ブロック内、または @INC このモジュールは、他のモジュールが使用される前に、スクリプトで使用されなければなりません。

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

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