私の Perl プログラムが Perl モジュールを使用している場合、モジュール コードを含むファイルの場所をどのように判断しますか?
たとえば、プログラムに次のものが含まれているとします。
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
どこに見えますか?
私の Perl プログラムが Perl モジュールを使用している場合、モジュール コードを含むファイルの場所をどのように判断しますか?
たとえば、プログラムに次のものが含まれているとします。
use MyModule1; # Example 1
use This::Here::MyModule2; # Example 2
どこに見えますか?
Perl インタープリター (perl プログラムを実行する) は@INC
、モジュールを含むファイルを検索するために呼び出される特別な配列を使用します。
@INC
配列内の各値はディレクトリ名です (ただし、以下の注を参照してください)。Perl は、以下に指定されたルールを使用して、ループ内でこれらのディレクトリ内を検索します。( @INC の内容がどのように決定されるかの詳細については、この SO 投稿を参照してください)。
を使い果たした後にモジュールのファイルが見つからない場合@INC
、プログラムのコンパイルはエラーで中止されます。モジュールのファイルが で指定されたディレクトリの 1 つにある@INC
場合、検索は の残りの部分を調べずに終了し@INC
ます。
にリストされている各ディレクトリ内で Perl がモジュール ファイルを検索する方法@INC
は次のとおりです。
まず、モジュール名の階層コンポーネント ( で区切られた単語::
) を最後のコンポーネント (ファイル名を形成するために使用されます) と階層パス (最後の の前にあるすべてのコンポーネント) に分割します::
。
モジュール名にコンポーネントが 1 つしかない場合 (上記の no::
などMyModule1
)、階層パスは空で、ファイル名はモジュールの名前です。この質問の 2 番目の例では、最後のコンポーネントはMyModule2
で、階層パスは になりますThis::Here
。
予想されるファイル名は、モジュール名の最後のコンポーネントに.pm
拡張子を追加することによって決定されます。たとえばMyModule1.pm
、MyModule2.pm
私たちの例では。
注: モジュール名は、ファイル/ディレクトリの命名で大文字と小文字が区別される Unix およびその他のオペレーティング システムでは、明らかに大文字と小文字が区別されます。
モジュールのディレクトリは、次のように決定されます。
から次のディレクトリを取得する-例として@INC
言ってみましょう/usr/lib/perl
/
モジュール名の階層パス (存在する場合) を取得し、"::" をオペレーティング システムがディレクトリ区切り文字として使用する任意の文字に置き換えることにより、そのディレクトリのサブディレクトリを形成します。2 つの例では、最初のモジュールは/usr/lib/perl
(サブディレクトリなし) で検索され、2番目のモジュールは で検索され/usr/lib/perl/This/Here
ます。
注: 上記は少し簡略化したものです。@INC
サブルーチン参照とオブジェクト参照も含まれる場合があります。これらは、上記の #2 ロジックで指定されたディレクトリでルックアップを実行する代わりに、カスタム コードが指定するモジュールをロードします。この機能はめったに使用されないようで、この記事では全体@INC
にディレクトリのみが含まれていることを前提としています。
@INC
に 2 つのサブディレクトリが含まれ
ていると仮定して、特定の例を見てみましょう("/usr/lib/perl", "/opt/custom/lib")
。
次に、Perl は次のように検索します。
================================================== ======================== | | モジュール | # を試してください | 試すファイル ================================================== ======================== | | MyModule1 | 1 を試す | /usr/lib/perl/MyModule1.pm | | MyModule1 | 2 を試す | /opt/custom/lib/MyModule1.pm ================================================== ======================== | | これ::ここ::MyModule2 | 1 を試す | /usr/lib/perl/This/Here/MyModule2.pm | | これ::ここ::MyModule2 | 2 を試す | /opt/custom/lib/This/Here/MyModule2.pm ================================================== ========================
Perl インタープリターは、そのファイルがいずれかの場所にある場合は検索を停止し、そのファイルが別の場所にあるかどうかを確認しようとしないことを思い出してください。たとえば、/usr/lib/perl/This/Here/MyModule2.pm
存在する場合、Perl は を探したり、存在を気にしたりしません/opt/custom/lib/This/Here/MyModule2.pm
。
注: Perl インタープリターがrequire
Perl モジュールをインポートするために -like メカニズムを使用している場合は常に @INC が使用されます。これも:
require
ディレクティブ自体use MyModule
ステートメント (require+import と同等)use base
(require+"push @ISA" と同等)-M
コマンド ライン パラメータこれは質問に直接答えるものではありませんが、使用するモジュール ファイルへのフル パスを特定するための簡単な方法をいくつか紹介します。
コマンドラインから@INC配列のデフォルトの内容を他の多くの情報とともに表示するには:
perl -V
Carpモジュールの場所を知りたい場合:
perldoc -l Carp
スクリプト内で%INCハッシュの内容を出力すると、特に@INCをデフォルトから変更した場合に、実際に使用しているモジュールを特定するのに役立ちます。
use Carp;
print $INC{'Carp.pm'};
この単純なスクリプトを使用して、正規表現に一致するインストール済みの Perl モジュールを検索し、異なるディレクトリにある重複モジュールを特定することもできます。
perlfuncuse
のドキュメントによると:
モジュール LIST を使用する
通常、特定のサブルーチンまたは変数名をパッケージにエイリアスすることにより、名前付きモジュールから現在のパッケージにいくつかのセマンティクスをインポートします。とまったく同等です。
BEGIN { require Module; Module->import( LIST ); }
ただし、Module はベアワードでなければなりません。
重労働require
も同様で、require
ドキュメントには
EXPR がベアワードの場合、require は
".pm"
拡張子を想定し、ファイル名を に置き換え"::"
て"/"
、標準モジュールを簡単にロードできるようにします。この形式のモジュールのロードでは、名前空間が変更されるリスクはありません。つまり、これを試してみると:
require Foo::Bar; # a splendid bareword
require 関数は、配列
"Foo/Bar.pm"
で指定されたディレクトリ内のファイルを実際に探します。@INC