1

私は時々この問題に遭遇します。何らかの理由で、エクスポートされたサブルーチンを呼び出そうとすると「未定義のサブルーチン」エラーが発生します。成熟したコードでは、突然発生するように見えるため、理由がわかりません。

前回それが起こったとき、私は「package_2 :: exported_sub()」のようなものを使用することに頼ったと思います。今回は機能しましたが、package_2の別のサブに対してエラーが返されました。「usepackage_2;」を入れても 上記の行では役に立ちません!私が考えることができる唯一のことは、エクスポートされたサブが何らかの形で未定義であるということです。

私のコードは次のようになります。

ファイルpackage_1.pm:

package package_1;

require Exporter;
@ISA = qw( Exporter );

@EXPORT = qw(
local_sub
);

use package_2;
use strict;
use warnings;
use diagnostics;

sub local_sub {
  &exported_sub;
}

ファイルpackage_2.pm:

package package_2;

require Exporter;
@ISA = qw( Exporter );

@EXPORT = qw(
exported_sub
);

use strict;
use warnings;
use diagnostics;

sub exported_sub {
 # do something
}

私はもう終わりです...これがポップアップしたとき、私は無関係のホットチケットに取り組んでいました、そしてユーザーテストは明日始まります!

前もって感謝します!


アップデート:

池上、修正してくれてありがとう!でも、興味があります。私はこれに再び遭遇しましたが、今回は循環依存を見つけることができませんでした。私はそれを1行に絞り込みました:

$row->{$attr} = ' ' unless ( $row->{$attr} );

明らかに、この行は使用または要求とはまったく関係ありません!Apacheのログを調べましたが、目立つものは何もないようですが、見つけたものはすべて解決するように機能します。さらに警告を受け取ることができるかどうかも確認します。

それとは別に、次のステップとして何をお勧めしますか?

ありがとう!

4

3 に答える 3

4

循環依存関係があると思われます。package_1はpackage_2を使用し、package_2はpackage1を(直接的または間接的に)使用します。

以下は、私が最初にPerlMonksで公開したソリューションです:http://www.perlmonks.org/? node_id = 778639


[この手法を使用する必要性は、システムの設計上の欠陥を示す非常に強力な指標ですが、設計上の欠陥を修正するためのリソースが常に利用できるとは限らないことを認識しています。]

ModAがModBを使用し、ModBがModAを使用し、ModAまたはModBが他方からシンボルをインポートする場合、一方はコードの実行順序に注意を払う必要があります。問題を回避するために私が見つけた最善の方法は、他のモジュールをロードする前にエクスポーターをセットアップすることです。

ModA.pm

package ModA;

use strict;
use warnings;

BEGIN {
   our @ISA = qw( Exporter );
   our @EXPORT_OK = qw( ... );
   require Exporter;
}

use This;
use ModB;
use That;

...

1;

ModB.pm

package ModB;

use strict;
use warnings;

BEGIN {
   our @ISA = qw( Exporter );
   our @EXPORT_OK = qw( ... );
   require Exporter;
}

use This;
use ModA;
use That;

...

1;
于 2012-08-30T19:10:30.780 に答える
1

あなたのuseラインは、そのようなものではなく、まさにそのようなものであると確信していますuse package_2 qw(xyz);か?

後者は、Exporterのimport()サブルーチンが呼び出し元モジュールにエクスポートするものを定義します。

于 2012-08-30T17:48:08.180 に答える
0

私の経験があなたのケースに合うことを願っています。Perlパッケージ名は名前空間で埋める必要があります。モジュールファイルがパス$PERL_LIB/ Fruit / Apple.pmにある場合次に、モジュールファイルで、名前空間Fruit::を指定する必要があります。

package Fruit::Apple;

.......

あなたが書くだけなら

package Apple;

.......

コンパイルエラーはありません。ただし、モジュールファイルApple.pmでメソッドを呼び出すと、「未定義のサブルーチン」エラーが発生します。

于 2016-08-08T11:38:06.147 に答える