≫use と require
Perl で外部ライブラリなりモジュールなりをロードする命令には、use と require の2つがある。
使い分けはどうすれば良いのか。
まず、大前提が2つ。
使い分けはどうすれば良いのか。
まず、大前提が2つ。
use は Perl5以上でないと使えない
require はバージョンを問わず使える
use はコンパイル時に評価される
require は実行時に評価される
≫評価されるタイミングの違い
use は、実行時最初に読み込まれるので、スクリプトのどこに書いても、全て最初(コンパイル時)にメモリにロードされます。
require はスクリプトの実行時に逐次呼ばれるので、必要なときだけメモリにロードするという制御が可能です。
例えば、
対して、ExampleUse は、$str の値に関わらず、スクリプトがコンパイルされるとともにメモリにロードされます。
したがって、
例えば、実行する可能性の低いルーチンをライブラリ化して、必要なときのみ require すれば、スクリプト全体の起動オーバーヘッドを軽減できます。
また、
サーバで常駐したり、子プロセスを fork するようなスクリプトを実行する場合は、モジュールを use することでメモリ使用率を軽減することができるのです。
require はスクリプトの実行時に逐次呼ばれるので、必要なときだけメモリにロードするという制御が可能です。
例えば、
if($str eq 'ok'){
require 'ExampleRequire.pm';
use ExampleUse;
}
この場合、ExampleRequire.pm は、$str が ok の場合にロードされます。require 'ExampleRequire.pm';
use ExampleUse;
}
対して、ExampleUse は、$str の値に関わらず、スクリプトがコンパイルされるとともにメモリにロードされます。
したがって、
例えば、実行する可能性の低いルーチンをライブラリ化して、必要なときのみ require すれば、スクリプト全体の起動オーバーヘッドを軽減できます。
また、
サーバで常駐したり、子プロセスを fork するようなスクリプトを実行する場合は、モジュールを use することでメモリ使用率を軽減することができるのです。
≫BEGIN, CHECK, INIT ルーチン
use されるモジュールの中では、BEGIN, CHECK, INIT ルーチンが実行できます。
BEGIN, CHECK, INIT ルーチンがどういうものかは、以下のコードを参考にしてください。
BEGIN, CHECK, INIT ルーチンは、sub を省略して書くことが出来る特殊なサブルーチンです。
BEGIN, CHECK, INIT ルーチンは、メインルーチンよりも先に、コールされなくても実行されます。
この、特殊な BEGIN, CHECK, INIT ルーチンが use されるモジュール内にあった場合、コンパイルされた後に、メインルーチンより先に実行されます。
require では、ロードすると同時に、ライブラリ内の BEGIN ルーチンだけが実行できます。
以下の BeCheIn.pm でテストします。
[BeCheIn.pm]
プログラミングの並び順で実行され、BEGIN ルーチンは、require された時点で、実行されています。
また、CHECK, INIT ルーチンは実行されません。
次に、use して実行するメインルーチン。
メインルーチンが実行される前に use するモジュール BeCheIn.pm の BEGIN, CHECK, INIT ルーチンが実行されています。
BEGIN, CHECK, INIT ルーチンがどういうものかは、以下のコードを参考にしてください。
#!/usr/bin/perl
# メインルーチン
print "メインルーチンでの出力\n";
exit;
# BEGIN, CHECK, INIT ルーチン
BEGIN {
print "BEGINでの出力\n";
}
CHECK {
print "CHECKでの出力\n";
}
INIT {
print "INITでの出力\n";
}
実行結果は、
# メインルーチン
print "メインルーチンでの出力\n";
exit;
# BEGIN, CHECK, INIT ルーチン
BEGIN {
print "BEGINでの出力\n";
}
CHECK {
print "CHECKでの出力\n";
}
INIT {
print "INITでの出力\n";
}
BEGINでの出力
CHECKでの出力
INITでの出力
メインルーチンでの出力
となります。CHECKでの出力
INITでの出力
メインルーチンでの出力
BEGIN, CHECK, INIT ルーチンは、sub を省略して書くことが出来る特殊なサブルーチンです。
BEGIN, CHECK, INIT ルーチンは、メインルーチンよりも先に、コールされなくても実行されます。
この、特殊な BEGIN, CHECK, INIT ルーチンが use されるモジュール内にあった場合、コンパイルされた後に、メインルーチンより先に実行されます。
require では、ロードすると同時に、ライブラリ内の BEGIN ルーチンだけが実行できます。
以下の BeCheIn.pm でテストします。
[BeCheIn.pm]
package BeCheIn;
use strict;
INIT { print "INITの出力\n" }
BEGIN { print "BEGINの出力\n" }
CHECK { print "CHECKの出力\n" }
sub hoge { print "hogeの出力\n" }
1;
BeCheIn.pm を require して実行するメインルーチン。
use strict;
INIT { print "INITの出力\n" }
BEGIN { print "BEGINの出力\n" }
CHECK { print "CHECKの出力\n" }
sub hoge { print "hogeの出力\n" }
1;
#!/usr/bin/perl
print "メインルーチンの出力\n";
require 'BeCheIn.pm';
BeCheIn::hoge();
実行結果は、
print "メインルーチンの出力\n";
require 'BeCheIn.pm';
BeCheIn::hoge();
メインルーチンの出力
BEGINの出力
hogeの出力
となります。BEGINの出力
hogeの出力
プログラミングの並び順で実行され、BEGIN ルーチンは、require された時点で、実行されています。
また、CHECK, INIT ルーチンは実行されません。
次に、use して実行するメインルーチン。
#!/usr/bin/perl
print "メインルーチンの出力\n";
use BeCheIn;
BeCheIn::hoge();
実行結果は、
print "メインルーチンの出力\n";
use BeCheIn;
BeCheIn::hoge();
BEGINの出力
CHECKの出力
INITの出力
メインルーチンの出力
hogeの出力
となります。CHECKの出力
INITの出力
メインルーチンの出力
hogeの出力
メインルーチンが実行される前に use するモジュール BeCheIn.pm の BEGIN, CHECK, INIT ルーチンが実行されています。
≫Exporter モジュールによる関数のインポート
use は、Exporter モジュールによる関数の自動インポートが可能ですが、require では、不可能です。
以下のようなライブラリを考えます。
[ Exptr.pm ]
では、require するメインルーチンの場合。
require の場合は、自動実行することはできませんが、手動で use と同様の振る舞いを実現できます。
ってな感じで、いろいろ調べてみると、上記のような違いがあるようです。
以下のようなライブラリを考えます。
[ Exptr.pm ]
package Exptr;
use base Exporter;
use strict;
our @EXPORT_OK = qw(hoge);
sub hoge { print "hogeの出力\n" }
1;
use で実行するメインルーチン
use base Exporter;
use strict;
our @EXPORT_OK = qw(hoge);
sub hoge { print "hogeの出力\n" }
1;
#!/usr/bin/perl
use Exptr qw(hoge);
hoge();
実行結果は、
use Exptr qw(hoge);
hoge();
hogeの出力
正常に print が実行されます。では、require するメインルーチンの場合。
#!/usr/bin/perl
require 'Exptr.pm';
hoge();
実行してみると、
require 'Exptr.pm';
hoge();
Undefined subroutine &main::hoge called at ./xxxxx.xxx line X.
hoge が定義されていないとのエラーになってしまいます。require の場合は、自動実行することはできませんが、手動で use と同様の振る舞いを実現できます。
BEGIN {
require MODULE;
MODULE->import(LIST);
}
require MODULE;
MODULE->import(LIST);
}
ってな感じで、いろいろ調べてみると、上記のような違いがあるようです。
TOP > スクリプト制作メモ > use と require