1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Perlでスクリプト/モジュールの両対応

Posted at

Perl で単一ファイルのスクリプトを作ったけど、スクリプト中の関数を他でも使えるようにしたいなと思うことがあります。規模が大きくなれば .pm 化してしまえばいいのですが、それほどの規模でもない場合もあります。スクリプト本体とモジュールをファイルを分けてもいいのですが、そうすると単一ファイルをコピーするだけという手軽さが失われるのがもったいない。なんかそういうときの方法があったよなぁというのをぐぐってて見つけたのがこちらです。

Perlで一枚岩のスクリプトをテスタブルにする

関数を他から利用するのも、関数をテストするのも、スクリプト/モジュールの両対応させるという点では同じですね。

そもそも何が問題か

例えば以下のようなスクリプトを作ったとします。

script.pl
# !/usr/local/bin/perl

use strict;
use warnings;

{
  if(@ARGV < 1) {
    print "usage\n";
    exit;
  }
  func();
}

sub func {
  print "func\n";
  # do something
}

スクリプトはちゃんと動作しますね。

$ ./script.pl
usage
$ ./script.pl param
func

次に script.plfunc を利用する別のスクリプトを作ります。

other.pl
# !/usr/local/bin/perl

use strict;
use warnings;

require './script.pl';

func();

これを実行しますと、script.pl のベタ部分の処理が実行され不本意に exit してしまいます。

$ ./other.pl
usage

どうしたらいいか

script.pl のベタ処理部分を、require された場合には実行しないように、以下のように書き換えます。

script.pl(改良版)
# !/usr/local/bin/perl

use strict;
use warnings;

if ($0 eq __FILE__) {
  if(@ARGV < 1) {
    print "usage\n";
    exit;
  }
  func();
}

sub func {
  print "func\n";
  # do something
}

1;

$0 は実行しているプログラムの名前が格納されます。スクリプトとして実行した場合には script.pl が、モジュールとして呼び出された場合は other.pl が入ります。

__FILE__ は自分自身のファイル名が格納されます。こちらはスクリプトでもモジュールでも、常に script.pl が入っています。

つまり、$0__FILE__ を比較することで、自分自身が今スクリプトとして実行しているか、モジュールとして呼び出されているかを判別できるわけですね。リンク先の記事に

pythonのif name == 'main':みたいな感じ。

とありまして、ああそういえば Python でこういうの見かけたんだと思い出した次第。

この状態で other.pl を実行すると、ちゃんと func() を呼び出せています。

$ ./other.pl
func
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?