I'm currently experimenting with reloading a module. The aim I'm hoping to achieve is to be able to change something in the defined subroutine in the module file, and then reload that module, using the new definitions.
Currently, I am changing the print statement in the test
subroutine to print "this is some different text" after waiting for the subroutine to execute the original code, and before the module is reloaded.
However, what I'm currently getting is the message:
Subroutine test redefined at /Test/testmodule.pm line 9.
This is exactly what I want, but the output is as follows.
this is some text Subroutine test redefined at /Test/testmodule.pm line 9. this is some text
What I'm hoping is that when the module is reloaded, and it realises that the subroutine has been redefined, is that next time it executes the test subroutine, it will refer to the new definition rather than the old one.
I've searched through previous questions on reloading modules, but the answers given were things like looping dependencies (package A uses B, and B uses A), or namespace collision in packages, but this is not the issue at hand here. I want the subroutine to be redefined, and the new definition used.
source code: 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::Relo开发者_StackOverflow中文版ad::Selective::Options->{ReloadOnlyIfEnvVarsSet} = 0;
Module::Reload::Selective->reload(qw(Test::testmodule)); #reload!
}
source code: testmodule.pm (in ./Test/
relative to main.pl)
#!/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;
Any pointers or references to tutorials would be brilliant. In fact, if the answer isn't incredibly simple, not telling me the answer directly will allow me to read your suggested material and gain an overall better understanding.
All required CPAN modules have been installed, and I can confirm that the testmodule.pm is being successfully written after changing.
OS: Scientific Linux CERN 6, kernel version 2.6.32-131.4.1.el6.x86_64
Perl: v5.10.1 (*) built for x86_64-linux-thread-multi
Many thanks in advance,
Owen.I don't know if this is the problem or not yet, but you are missing your package
statement in the module. This means test
is main::test
not Test::testmodule::test
.
Yep, it was a combination of cjm's answer and mine. This code works for me:
In Test/testmodule.pm
:
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;
In main.pl
:
#!/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;
}
To clarify, Perl 5 does not create a namespace when you create a .pm
file. It creates a namespace when you say package NamespaceName
or you reference that namespace like this
sub Test::testmodule::test {
print "this is some text, counter 1\n";
}
Since the test
function in your version was not in a the Test::testmodule
namespace, it never got reloaded.
You missed the part of the Module::Reload::Selective docs where it says to call import
after reload. (Although it uses the indirect object syntax, it's better to use a standard method call.) That is, you should have said:
Module::Reload::Selective->reload(qw(Test::testmodule)); #reload!
Test::testmodule->import; #reimport!
The reason is that Exporter essentially does:
*main::test = \&Test::testmodule::test;
That is, main::test
is assigned a reference to the current version of Test::testmodule::test
. Reloading the module redefines Test::testmodule::test
, but main::test
continues to refer to the original sub. Calling the import
method explicitly will copy the new version of the sub to main::test
.
You can stop issued warning by putting
no warnings 'redefine';
into loaded module.
Also please note that reloading is quite fragile concept and it might limit what you can do within your modules.
精彩评论