2011-07-20 29 views
4

現在、モジュールのリロードを試しています。私が達成しようとしている目的は、モジュールファイルの定義されたサブルーチンで何かを変更し、新しい定義を使用してモジュールをリロードすることです。モジュールのリロードとPerlでのサブルーチンの再定義

現在、testサブルーチンのprint文を変更して、サブルーチンが元のコードを実行するのを待ってから、モジュールがリロードされる前に "これはいくつかの異なるテキストです"と表示します。
Subroutine test redefined at /Test/testmodule.pm line 9.

これは私が欲しいものを正確にですが、次のように出力されている:

しかし、私は、現在取得しています、メッセージです。

this is some text 
Subroutine test redefined at /Test/testmodule.pm line 9. 
this is some text 

私は何を望んでいることは、それはではなく、新しい定義を参照します、次回はそれがテストサブルーチンを実行することをされたモジュールがリロードされたときにということであり、それは、サブルーチンが再定義されていることを実現します古いもの。

モジュールをリロードする際に以前の質問を検索しましたが、回答のループ(パッケージAはBを使用し、BはAが使用されます)やパッケージ内の名前空間の衝突がありましたが、ここに。 I サブルーチンが再定義され、新しい定義が使用されます。

ソースコード: main.pl

#!/usr/bin/perl 
use strict; 
use warnings; 
use Module::Reload::Selective; 
use Test::testmodule; 

while(1) { 
    test(); #run module's define subroutine 
    sleep(5); #stop terminal from being flooded too quickly 

    #Ensure that the module is reloaded 
    $Module::Reload::Selective::Options->{SearchProgramDir} = 1; 
    $Module::Reload::Selective::Options->{ReloadOnlyIfEnvVarsSet} = 0; 
    Module::Reload::Selective->reload(qw(Test::testmodule)); #reload! 
} 

ソースコード:(main.plから./Test/相対)testmodule.pm

#!/usr/bin/perl 
use strict; 
use warnings; 

# allow exportation 
require Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw(test); 

sub test { 
    print("this is some text\n"); # this line is edited in the source file to 
            # 'print("this is some different text\n");' 
} 
1; 

任意のポインタまたは参照チュートリアルには華麗です。実際、答えが信じられないほど単純ではない場合、答えを直接私に伝えないと、私はあなたの提案された資料を読んで全体的により良い理解を得ることができます。

必要なすべてのCPANモジュールがインストールされており、変更後にtestmodule.pmが正常に書き込まれていることを確認できます。

OS:科学のLinux CERN 6、カーネルバージョン2.6.32-131.4.1.el6.x86_64
のPerl:v5.10.1(*)はx86_64-linuxのスレッドのマルチ

用に構築

多くのありがとうございました。
オーウェン

+0

どのような新しい定義ですか?あなたは同じ出力を得る同じサブをリロードしています。 – TLP

+1

ありがとうございます。 2番目の段落では、_testmodule.pm_でソースコードの行を変更することに言及します。投稿を編集してより明示的にする必要があります。これを私の注意を引くことに感謝します。 – OwenD

答えて

4

問題があるかどうかわかりませんが、モジュールにpackageステートメントがありません。これは、testmain::testではなく、Test::testmodule::testであることを意味します。

うん、それはcjmの回答と私の組み合わせだった。このコードは、私の作品:Test/testmodule.pm

main.pl
package Test::testmodule; 

use strict; 
use warnings; 

# allow exportation 
require Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw(test); 

sub test { 
    print "this is some text, counter 1\n"; 
} 

1; 

#!/usr/bin/perl 
use strict; 
use warnings; 
use Module::Reload::Selective; 
use Test::testmodule; 

while(1) { 
    test(); #run module's define subroutine 

    my $module = do { 
     open my $fh, "<", "Test/testmodule.pm" 
      or die "could not open the module: $!"; 

     local $/; 
     <$fh>; 
    }; 

    $module =~ s/counter ([0-9])/"counter " . ($1 + 1)/e; 

    open my $fh, ">", "Test/testmodule.pm" 
     or die "could not open the module: $!"; 

    print $fh $module; 

    close $fh; 

    #Ensure that the module is reloaded 
    $Module::Reload::Selective::Options->{SearchProgramDir} = 1; 
    $Module::Reload::Selective::Options->{ReloadOnlyIfEnvVarsSet} = 0; 
    Module::Reload::Selective->reload(qw(Test::testmodule)); 
    Test::testmodule->import; 
} continue { 
    sleep 1; 
} 

明確にするためにあなたが.pmファイルを作成するときに、Perl 5の名前空間を作成しません。あなたがpackage NamespaceNameを言うとき、それは名前空間を作成するか、あなたのバージョンでtest機能がTest::testmodule名前空間ではなかったので、あなたがこの

sub Test::testmodule::test { 
    print "this is some text, counter 1\n"; 
} 

のように、その名前空間を参照し、それは決してリロードしないしまいました。

+0

ああ、私はパッケージの宣言を忘れてしまった...それは**常に**私と一緒に一日の終わりには本当に簡単な何か... あなたの答えをありがとう、それは多くの助けになりました。 EDIT:コードではなくファイルを直接変更したときにも機能します。助けてくれてありがとう(そしてcjm)ありがとう! – OwenD

2

あなたはロードされたモジュールに

no warnings 'redefine'; 

を置くことによって発行された警告を停止することができます。

リロードは非常に壊れやすい概念であり、モジュール内でできることを制限することがありますのでご注意ください。

+1

ありがとうございます。しかし、警告は私の問題ではありません。問題は、サブルーチンの新しい定義を使用しています。 – OwenD

3

リロード後にimportと呼ぶと言われているModule::Reload::Selective文書の部分を見逃しました。 (それが間接オブジェクト構文を使用しますが、それは標準のメソッド呼び出しを使用することをお勧めします。)、あなたが言っているはずであること:

Module::Reload::Selective->reload(qw(Test::testmodule)); #reload! 
Test::testmodule->import;        #reimport! 

理由はExporterは基本的にないことである:

*main::test = \&Test::testmodule::test; 

は、main::testの最新バージョンの参照番号がTest::testmodule::testと割り当てられています。モジュールをリロードするとTest::testmodule::testが再定義されますが、main::testは引き続き元のサブを参照します。 importメソッドを明示的に呼び出すと、サブの新しいバージョンがmain::testにコピーされます。

+1

その答えをありがとうございました。有望なことですが、残念なことに、再インポートは違いがないようです。おそらく、それは間違った範囲を持つ新たに再インポートされたサブルーチンと関係がありますか?私。サブルーチンは全体としてファイルの代わりに 'while'ブロックにしかスコープされません。 – OwenD

関連する問題