web-dev-qa-db-ja.com

@INCにないディレクトリでPerlモジュールを「使用」するにはどうすればよいですか?

スクリプトの親ディレクトリにモジュールがあり、それを「使用」したいです。

私が行った場合

use '../Foo.pm';

構文エラーが発生します。

私がやろうとしました:

Push @INC, '..';
use EPMS;

そして.. @INCに表示されないようです

私はおかしくなりそうだ!ここで何が問題なのですか?

51
Frew Schmidt

useはコンパイル時に行われるため、これは機能します。

BEGIN {Push @INC, '..'}
use EPMS;

しかし、より良い解決策はuse lib、これは上記のより良い記述方法です。

use lib '..';
use EPMS;

ただし、別のディレクトリから実行している場合は、FindBinの使用が推奨されます。

use FindBin;                     # locate this script
use lib "$FindBin::RealBin/..";  # use the parent directory
use EPMS;
93
ephemient

変更できる方法はいくつかあります@INC

  • perlrun に記載されているPerl5LIBを設定します

  • コマンドラインで-Iスイッチを使用します。これも perlrun に記載されています。 Perl5OPTでこれを自動的に適用することもできますが、そうする場合はPerl5LIBを使用してください。

  • use libプログラム内。ただし、これは脆弱です。別のマシン上の別の人が別のディレクトリに持っている可能性があるためです。

  • 手動で変更@INC、useを使用してモジュールを取得する場合は、コンパイル時に必ず実行してください。それはあまりにも多くの作業です。

20
brian d foy

個人的には、自分のモジュール(自分用または制御可能なシステム用に作成したモジュール)を特定のディレクトリに保持し、サブディレクトリに配置することを好みます。次のように:

/www/modules/MyMods/Foo.pm
/www/modules/MyMods/Bar.pm

そして、それらを使用する場所:

use lib qw(/www/modules);
use MyMods::Foo;
use MyMods::Bar;

余談ですが、プッシュに関しては、太い矢印のコンマを好みます。

Push @array => $pushee;

しかし、それは好みの問題です。

12
Berserk

@ephemientが前述したように、「use lib」が答えです。もう1つのオプションは、使用する代わりにrequire/importを使用することです。これは、モジュールがコンパイル時にロードされるのではなく、実行時にロードされることを意味します。

これにより、@ INCを変更したときに変更したり、モジュール名の代わりにファイルへのrequireパスを渡すことができます。 「perldoc -f require」から:

EXPRがベアワードの場合、requireは「.pm」拡張子を想定し、ファイル名の「::」を「/」に置き換えて、標準モジュールを簡単にロードできるようにします。この形式のモジュールのロードは、ネームスペースを変更するリスクはありません。

7
zigdon

Pushが-およびuseが早期に処理される前に、useを処理する必要があります。ですから、チャンスを得るにはBEGIN { Push @INC, ".."; }が必要だと思います。

2

「perldoc -f use」で報告されているとおり:

それはまったく同等です
BEGIN { require Module; import Module LIST; }
ただし、モジュールは裸語でなければなりません。

別の言い方をすれば、「使用」は次と同等です。

  • コンパイル時に実行し、
  • パッケージ名をファイル名に変換し、
  • require--そのファイル名、および
  • import-そのパッケージを実行します。

そのため、useを呼び出す代わりに、BEGINブロック内でrequireおよびimportを呼び出すことができます。

BEGIN {
  require '../EPMS.pm';
  EPMS->import();
}

そしてもちろん、importを呼び出すときにモジュールが実際にシンボルのエクスポートやその他の初期化を行わない場合は、その行を省略できます。

BEGIN {
  require '../EPMS.pm';
}
1
Simon