CGI.pmを複数の自作モジュールで使用する際の注意点

このQ&Aのポイント
  • CGI.pmを別の複数の自作モジュールで使用する際の注意点について説明します。
  • 複数の自作モジュールでCGI.pmを使用する場合、標準入力STDIN経由での間接的な複数回読み込みは問題ありません。
  • 各モジュールから重複してCGI.pmを使用しても、CGI.pmは複数回読み込まれてもうまく処理されます。
回答を見る
  • ベストアンサー

CGI.pmを別の複数の自作モジュールでそれぞれuse。標準入力STDINのCGI.pm経由での間接的な複数回読み込みは大丈夫?

 CGI.pmを別の複数(少なくとも2つ)の自作モジュールで それぞれのuseします。 別の複数の自作モジュールは 別のcgiファイルから一回のcgiのプロセスで 両方(あるいは全部)useします。 この場合、標準入力STDINのCGI.pm経由での 間接的な複数回読み込みは大丈夫でしょうか? 通常はSTDINは一回のcgiのプロセスで一回しか読めないはずですよね? 各モジュールから重複useしても (もちろん複数の各モジュールで重複useしているのであり一つのモジュール内ではuse CGI;は一回のみです) CGI.pmのほうでうまく処理して複数回読んでくれるのでしょうか?

noname#179638
noname#179638
  • Perl
  • 回答数3
  • ありがとう数1

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

  • ベストアンサー
回答No.2

No1です。文意を間違えました。すみません。 package abc; use CGI; ・・・ package def; use CGI; ・・・ と言うことですよね? CGI.pmのソースコードがうまく追えなかったので確実ではありませんが、一度目にnewしたCGIオブジェクトでSTDINを読んでしまうので、二度目にnewしたCGIオブジェクトではパラメータが何も読めない ということになると思われます。 モジュールの汎用性から考えても、モジュール内でCGI.pmを使うということは避け、モジュール側にメインパッケージで取得したパラメータを渡す と言う実装にしたほうがよいと思われます。

その他の回答 (2)

回答No.3

No.1 の補足に回答いたします。 STDINに関係ないメソッドを呼ぶ文には全く問題ありません。 実証済みです。 > perl -MCGI -e "$c = new CGI(); $c = new CGI(); print $c->start_html;" < なお、useについてですが、Perlは内部でuseしたライブラリ名を記憶していて、同じモジュールをuseしない(2回目のuseは無視)ようになっているので、二カ所で同じモジュールをuseしても、全く問題ありません。

noname#179638
質問者

お礼

 TakamiChieさま、本当にありがとうございました。 実験してみたところPOSTやSTDINではなく GETの$ENV{'QUERY_STRING'}であれば 一回のcgiのプロセスで何度でも読めるようです(少なくとも2回は読めました)。  直接のご回答であるANo.2のほうに20ポイント出しておきます。

回答No.1

解析はしていないので詳しいことはわかりませんが、CGI.pmをuseした地点で、ほかのコードからSTDINをさわるという行為は避けたほうが良さそうです。 CGI.pmはコマンドラインからのオプション指定も簡単に拾えるため、以前デスクトップ用のスクリプトで使ってみたことがありますが、use後最初にSTDINから読み込みを行おうとした時点で動作がおかしくなりました。 ――うまく使えば可能なのかも知れませんが、バグが発生する可能性が高いため、そのような処理はしないほうがいいと思います。ループなどをうまく使い、それ以外の方法を検討することをおすすめします。

noname#179638
質問者

補足

 TakamiChieさま、ご回答ありがとうございます。 一回のcgiのプロセスでCGI.pmの2回目のnewの場合、 start_htmlなどのPOSTやSTDINと無関係なCGI.pmのメソッドの動作は どうなるのでしょうか?

関連するQ&A

  • useする自作のモジュールについて。

    perlで自作のモジュールをuseしたいのですが、その際参照するディレクトリをモジュールごとに指定するためにはどうしたらいいのでしょうか? 例えばあるスクリプト中でA.pmとB.pmをuseして、A.pmは一つ上の階層、B.pmは二つ上の階層のディレクトリを参照するという形です。 この際libで呼ぶのではなくアパッチでA.pmの場合はここを参照、B.pmの場合はこことしたいのですがどなたかご教授下さい。 環境 apache2.2系 Linux(ubuntu)

  • Perlのクラス(*.pm)からuseする側の*.cgi内ののスカラやハッシュ、配列の参照は可能でしょうか?

     Perlのクラス(*.pm)からuseする側の*.cgi内ののスカラやハッシュ、配列の参照は可能でしょうか? いろいろなサーバに対応させやすくするため 1行目(Perlのパス)や各種モジュールのパスや設定情報を*.cgiに書いてプログラム本体は*pmに置きたいのです。 それとももっといい方法がございますでしょうか。  教えて!ください。

    • ベストアンサー
    • Perl
  • パッケージとモジュールについて

    こんにちは。Perlを学習し始めた初心者です。 Perl 5.87を使っており、標準モジュールを使う方法を書籍で読みました。 例えば、フォームに入力、送信されたデータを処理するために use CGI; と最初に記述して使うことができますが、 別のエラー処理の構文を見ると $CGI::POST_MAX と1行目に記述してあります。 パッケージとモジュールの概念が、よく分かっていないので戸惑って います。 C:\perl\lib にある、CGI.pmというモジュールを使用していると思う のですが、use CGI;と記述するときと $CGI::と記述するとき、何が異なるのでしょうか? 後者はCGI.pmの中にある、POST_MAX変数を使うということでしょうか? パッケージという言葉を見ても、よく分からずネットで随分調べましたが、余計に分からなくなってしまいました。 お忙しいところ申し訳ありませんが、よろしくお願い致します。

    • ベストアンサー
    • Perl
  • チェックボックスで得た複数回答をCGIモジュールを用いて簡潔に取り出すには

     <input type="checkbox" name="id" value="0">  <input type="checkbox" name="id" value="1">  <input type="checkbox" name="id" value="2">  <input type="checkbox" name="id" value="3"> のようなフォームのキーと値を、CGIの方では%inで受け取ります。 まずCGIモジュールを用いてキーと値を$keyと$valに格納したのち、idというキーは4つの値を受け取るので、  foreach my $key ($q->param()) {   my $val=$q->param($val);   if(defined($in{$key)) {    $in{$key}.="\0";   }   $in{$key}.=$val;  } 私のイメージでは、この処理で  $in{'id'}="0\01\02\03"; が得られるつもりでした。 ところが実際には$q->param('id')で取り出せるのは最初の"0"のみで、したがって得られる結果は  $in{'id'}="0"; となります。 CGIモジュールを使わなければ、  my $buf;  if(ENV{'REQUEST_METHOD'} eq "POST") {   read(STDIN,$buf,$ENV{'CONTENT-LENGTH'});  }  else {   $buf=$ENV{'QUERY_STRING'};  }    foreach(split(/&/,$buf)) {   my ($key,$val)=split(/=/);      if(defined($in{$key)) {    $in{$key}.="\0";   }   $in{$key}.=$val;  } のようにして、イメージ通り  $in{'id'}="0\01\02\03"; を得られますが、CGIモジュールは他でも使うので、どうせならCGIモジュールを使った簡便なコーディングが出来ないものかと思案する次第です。 しかしながら私に思いつく方法は  <input type="checkbox" name="id0" value="0">  <input type="checkbox" name="id1" value="1">  <input type="checkbox" name="id2" value="2">  <input type="checkbox" name="id3" value="3"> として、まずCGIモジュールを用いた上記の方法で$in{'id0'}~$in{'id3'}までを生成し、次に  if(/(\w+)\d/) {   if(defined($in{$1})) {    $in{$1}.="\0";   }   $in{$1}.=$val;  } とやる方法しか思いつきません。 チェックボックスを用いて複数回答を得るというのはよくある話なので、CGIモジュールにもっと良いコーディングの仕方がありそうな・・・と思ってしまうのですが、これが最善の方法なのでしょうか?

    • ベストアンサー
    • Perl
  • mod_perlのキャッシングに関して

    現在RedhatLinuxでapache+mod_perlを動かしています。 自作のモジュールXXXX.pmを使用した(useにて)CGIを動かしているのですが、XXXX.pmに変更を加えても、それが反映されません。 Apache::Registoryを設定しているのですが、.cgiはうまく再コンパイルされているようなのですが、.pmを使用するとうまくいきません。ディレクトリは同一です。 mod_perlのキャッシングのせいだと思うのですが、回避の方法がご存知の方がいましたら教えて下さい。

  • 自作モジュールを認識しない

    Perl 5.8 自作モジュールのあるフォルダをFOLDER、モジュールの名前をMODULEとして以下のコードを実行してもモジュールが見つからない旨のメッセージが表示されます。 モジュールの拡張子は.pmを使用しています。 また、モジュールを標準の拡張モジュールのおき場所に置いた場合は適切に動作しました。 #! /usr/local/bin/perl push (@INC ,FOLDER); use MODULE;

    • ベストアンサー
    • Perl
  • 一括してモジュールを読み込みたい

    最近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
  • CGI..pmをテストしようとするとエラーがでます。

    こんにちわ。windowsXPを使用していますが、CGI.pmをテストしようとするとエラーが出てきます。内容は「perl.exe.アプリケーションエラー 0x28085b5dの命令が0x00000004のメモリーを参照しました。メモリが\"written\"になることは出来ません。」というものです。どうすれば解決するのでしょうか。教えて下さい。勉強不足で全く解りませんが、自分で原因をわかる範囲で考えるとCGI.pmをplの中で複数回use CGIという最初の箇所から入れたからなのか…でも全く解りません。サブルーチンの中で一回一回use~書かなくても良いのでしょうか?それも解らないので教えて下さい。最初は一回一回subの中で書かずファイル冒頭に書いただけだったのですが、テストするとプロンプトでsubの中で呼ばれているsubを「不明なsubである」と出たので、ブロック中で最初から書いてみました、するとそれが出なくなりました。でもブロックの中で同ページでもuse CGI;$q=new CGIと書かなくてはいけないのだろうかと半信半疑です。CGI.pmは今回初めてテストしてみました。理解していない部分が多いですが、エラーとuseの件よろしくお教え下さい。

  • Perl MIME::Parser モジュールを使わないで添付を取り出す

    携帯から.forwordを使ってCGIを起動しメールに添付されている画像を サーバーに保存する事を考えております。 MIME::Parser モジュールを使った方法はよく見かけるのですが モジュールを使わずに@line=<STDIN>だけで複数ある添付ファイルを取り出し保存する事はできるでしょうか?

  • 別サーバーのcgiを実行させる

    あるサーバーで動作しているcgiスクリプトから、別のサーバーに置いてあるcgiスクリプトを実行させる方法はあるでしょうか? require 'http://…/…/test.cgi'; としても実行することは出来ませんでした。 googleで検索したところrequireではURL指定ができないと解説しているサイトがありましたので、requireを使わずに、(CGI.pm等の標準モジュール(?))なども使わないで他のサーバーに設置したcgiを動作させる方法があれば、教えていただきたいです。

    • ベストアンサー
    • CGI