一括してモジュールを読み込みたい

このQ&Aのポイント
  • 最近Perlを始めました。利用するモジュールを各CGIファイルごとの先頭に宣言するのが面倒なので、Include.plなどのファイルを作って一括して読み込みたいと考えています。
  • しかし、CGIファイルで直接useの宣言を書くと、正常に動作することから、このような使い方でモジュールを読み込むことはできないようです。
  • また、自作モジュール内で他のモジュールを利用したい場合も、個別にuseの宣言を行う必要があります。PHPとは異なる挙動に困惑しています。
回答を見る
  • ベストアンサー

一括してモジュールを読み込みたい

最近Perlを始めました。(今まではPHPをやっておりました) 利用するモジュールを各CGIファイルごとの先頭に宣言するのが面倒なので、Include.plなどのファイルを作って一括して読み込みたいと考えています。 例えば以下のような感じです。 【Include.pl】 use strict; use Data::Dumper; use Fcntl qw(:DEFAULT :flock); use CGI; use CGI::Session ; use CGI::Carp qw(fatalsToBrowser); use Encode; use HTML::Template; 1; 上記のようなファイルを各CGIファイルの先頭で、 require 'include.pl'; とした場合に、使用できないモジュールがあります。 例えば、ファイルロックをしたくてflock(FILE, LOCK_EX)とするとエラーになってしまいます。 しかし、CGIモジュールは$q = CGI->new()と普通に利用できます。 モジュールは全てインストールされています。その証拠にCGIファイルに直接useの宣言を書けば動作します。 通常、このような使い方でモジュールのuseは有効にならないのでしょうか?? また、自分で作成したモジュール内で他のモジュールを利用したいといった場合、いちいちuseで宣言しなければならないのでしょうか。 mainとなるファイルでuse宣言しておくだけで、自作モジュール内で利用できると思ったのですが、いちいち宣言しなおさなければ利用できないようです。 挙動がPHPと違うため困惑しております。 どなたかご教授いただけないでしょうか。よろしくお願いいたします。

  • Perl
  • 回答数4
  • ありがとう数19

質問者が選んだベストアンサー

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

strict のような小文字のみからなる名前のものは、プラグマといって 扱いが通常のモジュールとは異なります。 strict に関しては、その有効範囲が use strict されたブロック (or ファイル)を越えることはありませんので、 require 'hogehoge.pl' としていて、hogehoge.pl が use strictしていてもその影響は呼び出し側には及びません。 後半は質問の意味がよく読み取れないのでパス。

begin96
質問者

お礼

ありがとうございます。 strict に関してはそういうことだったのですね。理解できました。 後半の部分に関しては説明が足りませんでした。 以下のようにしたいのですが・・。 <例> 【main.cgi】 1: reqiure include.pl 2: $m = MyModule->new; 3: print $m->get_pass('ABCDEFG'); 4: __END__ 【include.pl】 1: use CGI; 2: use Digest::MD5 qw/md5_hex/; 3: use MyModule; ←自作のモジュール 【MyModule.pm】 1: package MyModule; 2: sub get_pass{ 3: $class = shift; 4: $pass = shift; 4: $password = $pass; 5: return md5_hex($password) 6: } ※上記部分抜粋です 上記のような場合、MyModule.pmの5行目md5_hexがエラーになります。 include.plで"use Digest::MD5"と記述しておけば良いのかと思っていたのですが、MyModule.pmの先頭でも再度記述しなければいけないのでしょうか。 できればinclude.plファイルひとつでuseの宣言を済ませたいと考えています。

その他の回答 (3)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

> 最後にもう1点だけご質問なのですが、requireは1度読み込まれたら再度読み込まないように内部的に記憶しているようですが、 > useはそうでないとどこかのサイトで見たことがあります。 すみません。差し支えなければ、そしておぼえていらっしゃるのなら そのサイトを教えていただけませんか? 確かに require については、複数回同じモジュールを requireしても 実際に読み込まれるのは一回だけというのはその通りです。 use についてもドキュメント (perlfunc の use の項)に Imports some semantics into the current package from the named module, generally by aliasing certain subroutine or variable names into your package. It is exactly equivalent to BEGIN { require Module; Module->import( LIST ); } except that Module *must* be a bareword. (略) The "BEGIN" forces the "require" and "import" to happen at compile time. The "require" makes sure the module is loaded into memory if it hasn't been yet. とありますので、複数回指定したとしても実行されるのは一回だけだと思われます。 あーひょっとして >Module->import( LIST ); この部分のことでしょうか? いまちょっと試してみましたが、モジュールに import というメソッドがあれば、 use した回数だけ呼ばれてますね。 ただ、メモリの使用量云々については心配しないで大丈夫でしょう。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

> 上記のような場合、MyModule.pmの5行目md5_hexがエラーになります。 > include.plで"use Digest::MD5"と記述しておけば良いのかと思っていたのですが、 > MyModule.pmの先頭でも再度記述しなければいけないのでしょうか。 これは、 2: use Digest::MD5 qw/md5_hex/; によって、md5_hex というサブルーチンは、main というパッケージに属するようになります。 しかし、 1: package MyModule; と、パッケージを宣言してしまっているので 5: return md5_hex($password) これは、MyModule::md5_hex を検索しに行ってしまいます。 とりあえず ::md5_hex($password) とすれば見つけてくれますが、 あまり美しくはないですね。

begin96
質問者

お礼

詳しいご説明ありがとうございます! なるほどそういう動きをするのですね。原理が分かりました。 やはり各自作モジュールごとに、useで宣言を書いた方が綺麗ですね。 最後にもう1点だけご質問なのですが、requireは1度読み込まれたら再度読み込まないように内部的に記憶しているようですが、useはそうでないとどこかのサイトで見たことがあります。 もし各自作モジュールごとにuseで宣言を書いた場合、、例えばmainパッケージでuse Digest::MD5 として、自作モジュールでもuse Digest::MD5 とすると、2回読み込みされてしまうということでしょうか。 この場合メモリを余計に使用してしまうような気がするのですがどうなのでしょうか。特にuse CGI などは気になります。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

use と require って同じタイミングで処理されましたっけ? 試しに BEGIN { require 'Include.pl'; } としてみたらどうなるでしょうか?

begin96
質問者

お礼

ありがとうございます。 BEGIN { require 'Include.pl'; }にすると、flockはエラーがなくなりました! しかしuse strict は有効にはなりません。これは各ファイルごとに設定する必要があるのでしょうか。 また、自作のモジュールから別のモジュールを使いたい場合、やはりuseの宣言を自作モジュールにも記述しなければいけないのでしょうか。mainとなるCGIでinclude.plひとつ読み込んだだけでは、自作モジュールからの呼び出しは出来ないようでした。

関連するQ&A

  • use CGI

    サンプルスクリプトのなかに use CGI qw(:cgi :form); use CGI::Carp qw(fatalsToBrowser); use Image::Magick; と書かれていたのですがuse CGI::Carp qw(fatalsToBrowser);は意味わかったのでコメントアウトしましたがuse CGI qw(:cgi :form);は何を読み込んでいるのですか?コメントアウトしても大丈夫でしょうか? イメージマジックは使うのでそのままにしてあります よろしくお願いします

    • ベストアンサー
    • Perl
  • モジュールを使うときの負荷

    変な質問かも知れませんが宜しくお願いします。 CGIを作り、改良や新機能を追加するごとにスクリプトが膨らみ ファイルサイズが大きくなってしまいます。 その負荷を抑えるために、よく、 if分岐で必要に応じたパーツをrequireで読み込んで使っています。 これはとても効果があって本当に頻繁に使うのですが、 今回、モジュールを使いたいと思っています。 しかし、モジュールを使うときには、 useで宣言するのですよね? これでモジュールをインクルード出来る。と本には説明されています 問題はこのとき、結構な容量のあるモジュールをuseで宣言すると、 例えば、50kbの本体プログラムで 100kbのモジュールを使うと 宣言すると、もれなく150kb分のプログラムを動かしている状態に なってしまうのでしょうか? データベースなどを取り扱いたいのですが、use宣言しただけで 大きなモジュール分の負荷がかかるのであれば、悩みます。 どなたかお教え下さい。 また、こういう場合でも動作を軽くする方法があれば、そちらもお教え下さい。 データベースを使って処理するのと、面倒でも1ファイルずつOPEN、closeで split処理してデータを取るのとどちらが良いかかなり悩んでいます。 今回扱うデータがかなりの大きさになるもので・・・^^;; 変な質問ですが宜しくお願いします。

    • ベストアンサー
    • Perl
  • CGI::Carpを使っているのにInternal Server Error

    うまく動きません。コマンドラインでは作動するのですが、ブラウザではダメでした。  #! /usr/bin/perl -w  use Calendar::Simple;  use CGI::Carp qw(fatalsToBrowser);  use Data::Dumper;  use lib "/home/kojima/kojima00001/myperl/lib";  my @curr=calendar;  print Dumper(@curr); もっともその理由は分かりました。  use lib "/home/kojima/kojima00001/myperl/lib"; が  use Calendar::Simple; より後にあったことです。 さらに言うと、ブラウザで動かすためにはHTMLをサポートしていないといけませんが、このコードはHTMLをサポートしていません。 この2点を修正して、無事このプログラムはブラウザでもうまく動いたのですが、問題はうまく動いてくれていなかった時のブラウザの表示です。 Internal Sever Errorが出ていました。それじゃ何のことか分からなくて嫌だから  use CGI::Carp qw(fatalsToBrowser); と宣言してあるのです。 モノの本によると、この場合は  Software error:  Can't locate Calendar/Simple.pm in @INC (@INC containts: @INCに含まれるディレクトリがズラズラ・・・).  BEGIN failed--compilation aborted at calendar.cgi line3. というエラーメッセージが表示されるはず。 つまりCGI::Carpが機能していないことになります。 何故でしょう? お手数をお掛けします。

    • ベストアンサー
    • Perl
  • パスがうまく通らない

    Check.pmが  o:\public_html/post_pervice/cgi/lib にあります。 このモジュールを利用するために以下のようなプログラムを書きました。   #! /usr/bin/perl -w   use CGI::Carp qw(fatalsToBrowser);   unshift @INC, "o:/public_html/post_service/cgi/lib";   print join "\n",@INC;   use Check; この中の  use Check; をコメントで伏せて動かすと、   o:/public_html/post_service/cgi/lib   O:/usr/site/lib   O:/usr/lib のような表示がなされるので、  unshift @INC, "o:/public_html/post_service/cgi/lib"; はちゃんと機能しているようです。 しかし  use Check; のコメントを外して動かすと、   Can't locate Check.pm in @INC (@INC contains: O:/usr/site/lib O:/usr/lib .) at O:\public_html\post_service\cgi\showINC.pl line 8.   BEGIN failed--compilation aborted at O:\public_html\post_service\cgi\showINC.pl line 8. のようなエラーが出てしまいます。 何がいけないのでしょう。

    • ベストアンサー
    • Perl
  • モジュール入れたら・・・・・

    ホームページの引越しをしてるんですが xoopsに移し変えてるんですが モジュールのmyalbumを前のサーバーの中に入ってた奴をそのまま新しいサーバーにアップしたらモジュールの管理画面の下のほうにこのようなことが書かれてたんですが 「Notice [PHP]: Only variables should be assigned by reference in file modules/myalbum/include/get_perms.php line 9」 翻訳ソフトで解析したら 「通知[PHP]:変数だけは、ファイルmodules/myalbum/include/get_perms.php第9行で参照によって割り当てられなければなりません」 と出たのですが これってどういうことなのでしょうか?  いろいろと調べてみましたがやはりわからなかったのでここで質問させていただきました。 PHPに詳しい方どうかアドバイスお願いします。

  • CGI のモジュールをつかってファイルのアップロード

    use CGI qw(:standard); use File::Basename; $upimg1_pm = param('upimg1'); while (read($upimg1_pm, $buffer, 2048)) { $file .= $buffer; } $FileName = basename($upimg1_pm, ""); open UP,"> $img_dir/$FileName"; binmode UP; print UP $file; close UP; 上のようにファイルのアップロードのプログラムを書いたのですが、実際アップロードしたら C:\Documents and Settings\~top.gif のようにWindowsのローカルパスがそのままファイル名としてアップロードされてしまいました。 basenameはファイル名をとるモジュールときいていたのですがなぜこうなるのでしょうか? おそれいりますがご教授おねがいします。 もしかしてFile::Basename;のモジュールがないとか・・・ Perl5です。

    • ベストアンサー
    • CGI
  • PerlのCGIでフォームのテキスト配列をPerlで取得するには?

    フォームで通常は同じ名前のデータを取得することは無いのですが 表計算のように同じ名前の場合、データの取り出し方がわかりません。 以下、通常の1件の場合のソースです。 #!/usr/bin/perl $| = 1; use strict; our %in; use CGI::Carp qw(fatalsToBrowser); use CGI qw(:standard); require 'jcode.pl'; require 'cgi-lib.pl'; # #-----分岐----- &ReadParse; # 配列でない場合 my $namae = $in{'namae'} print "$namaeで名前が1件表示される"; # これをフォームで namaeが配列になった場合、 #<input type="text" name ="namae"> #<input type="text" name ="namae"> #<input type="text" name ="namae"> # のような場合、3件取得する場合 exit; __END__

    • ベストアンサー
    • CGI
  • opendir apache 絶対url

    apache上でcgi-bin/ファイル.cgiのファイル.cgiから特定のディレクトリハンドルを開くために #!/perl/perl/bin/perl -wT use strict; use CGI::Carp qw(fatalsToBrowser); opendir DH, "http://localhost/image/"; opendir DH, "http://localhost/image/" or die "error"; for (readdir DH){ print; } としたのですが オープンできません opendirのパスに絶対urlや相対urlを使用する方法はありませんか?

  • POST形式でファイルを送ると、CGIモジュールでエラーが出ます。

    ファイルを添付できるメールフォームを作ろうと思いました。 まず呼び出し側のHTMLファイルを以下のようにしました。   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">   <html>   <head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">   </head>   <body>   <form action="./filemail.cgi" method="post" enctype="multipart/form-data">    <input type="file" name="file-1"><br />    <input name="submit" type="submit" value="送信">   </form>   </body>   </html> しかし受け手のCGIの方でエラーが出ます。 エラー原因を調べるためプログラムのコードをとことんまで削りました。   #! usr/bin/perl -d      use strict;   use warnings;   use CGI::Carp qw(fatalsToBrowser);   use CGI;      our $q=new CGI; ・・・A      print $q->header(-charset=>'utf-8'),      $q->start_html(-charset=>'utf-8',             -lang=>'ja-JP'),      "うまくいった~~^^v\n",      $q->end_html; それでもエラーが出ます。エラー箇所はAの our $q=new CGI; です。 エラーメッセージは   Software error:   CGI open of tmpfile: No such file or directory です。 ちなみにコードを削りまくったこのプログラムはフォームデータとまるで関係ないので、ブラウザのURL窓にURLを手入力して呼び出してみました。  http://127.0.0.1//filemail.cgi これは目出度く正常に動作します。  うまくいった~~^^v またファイルを添付せずにフォームの送信ボタンをクリックしても正常に動作します。 そしてファイルを添付しても、フォームの送信方法をPOSTではなく、GETにしたら正常に動作します。 要するに、フォームの送信方法がPOSTの場合に、ファイルを添付して送信ボタンをクリックすると前述のエラーが出ます。 エラーメッセージからしてCGIモジュールで何か問題が起きているのですが、CGIモジュールとPOSTによるファイル送信は相性が良くないのでしょうか。それとも何か他にやるべきことがあるのでしょうか。 お手数をお掛けします。

    • ベストアンサー
    • Perl
  • フォームメール@PerlとActivePerlのモジュール

    Apacheで稼動しているメールフォームを、IISへ移動する事になりました。 現在IISがなくテストできない為、モジュールの代替案をご享受ください。 use NET::SMTP; → パッケージlibnetをインストールすればいい? use Jcode; → jcode.plを用意する? use CGI; → ??? 宜しくお願いいたします。

専門家に質問してみよう