Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hi,
I want a module to detect if it was loaded by "require" or "system". Can this be done in elegant way, or just adding and checking different argument passed by the caller?
More info.
I have working programs, where a Perl script, loaded from command line, will later "require" a module, and jump to a subroutine inside the module, and the rest of the package thereafter.
I checked that Perl will run a .pm script from command line, not neccessary have to be .pl.
I want to add to the .pm file more code that will only be executed if loaded from command line or "system" because I want to share most of the code in the module. The functionality of the module should stay as before. So I guess I need an "if statemt" at the beginning to check who was calling, but check what? :(
I am on Windows XP, Active State v5.8.3 built for MSWin32-x86-multi-thread
Thanks.
•Re: Dual personality: Module and script
by merlyn (Sage) on Aug 03, 2004 at 15:11 UTC
|
If I read you correctly (and it is still early in the morning here), you want caller:
caller EXPR
caller Returns the context of the current subroutine call. In sca
+lar
context, returns the caller's package name if there is a c
+aller,
that is, if we're in a subroutine or "eval" or "require",
+and
the undefined value otherwise. [....]
So, unless (defined caller) { ... } will execute that code if it's being brought in as the main level of the program, rather than a module.
| [reply] [d/l] [select] |
Re: Dual personality: Module and script
by tachyon (Chancellor) on Aug 03, 2004 at 15:07 UTC
|
As pointed out you really don't want to do this, but here is how anyway* ;-) This only works if you use the module not if you require if as when you use a module the modules import() method is called at the start of proceedings. This is not true for require when import is not called.
package MyModule;
use strict;
use Exporter;
use vars qw($VERSION @ISA @EXPORT $MOD_CALL );
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw( func1 );
sub func1 { return reverse @_ }
sub import { $MOD_CALL++; }
CHECK{ print $MOD_CALL ? "Called as a module\n" : "Called as a script\
+n" }
1;
On the rare occasions I have made a module a stand alone executable (usually for all the wrong laziness reasons) I have just used the presence of values in @ARGV to initiate script like behaviour. Generally you want to pass some data to a script anyway......
if ( @ARGV ) {
print "I'm a script!\n";
# do stuff
exit 0;
}
# only get to here if you we are a module
* Recall the story about getting enough rope to hang yourself?
| [reply] [d/l] [select] |
Re: Dual personality: Module and script
by BrowserUk (Patriarch) on Aug 03, 2004 at 22:34 UTC
|
#! perl -slw
package MyPackage;
...
return 1 if caller;
package main;
use Devel::StealthDebug;
our $ITERS ||= 10;
our $OTHER ||= 'default';
## run test code here
That allows me to embed the unit test code for the module directly into the module itself, keeping it all together.
The testcode then also serves as sample code for users (should any of my half-baked ideas ever get refined enough that I feel able to let it loose on the world :).
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] |
Re: Dual personality: Module and script
by eserte (Deacon) on Aug 03, 2004 at 15:53 UTC
|
I usually use the following code lines:
package My::Module;
use Getopt::Long;
sub process {
local @ARGV = @_;
# handle command line or named parameter options:
GetOptions(...) or die ...;
# here follows the rest of the script
}
return 1 if caller;
# This is executed only in "script" mode:
process(@ARGV);
# In "module" mode I have to write:
# use My::Module;
# My::Module::process(-bla => "foo", ...)
Of course there are variations of these scheme possible --- you just need the "return 1 if caller" line to distinguish between module code and script-only code.
| [reply] [d/l] |
Re: Dual personality: Module and script
by dragonchild (Archbishop) on Aug 03, 2004 at 14:56 UTC
|
It sounds like you're trying to be too clever. Modules are generally meant to be sourced in from other entities, like scripts. I wouldn't have executable modules, personally.
------
We are the carpenters and bricklayers of the Information Age.
Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose
I shouldn't have to say this, but any code, unless otherwise stated, is untested
| [reply] |
|
In the Python world, the sentiment is exactly the opposite. I remember reading in "Programming Python" this common idiom:
#!/usr/bin/env python
# module mymod2.py
def cube(n):
return n ** 3
# when 'import'ed, __name__ is 'mymod2'
# when executed, __name__ is '__main__'
if __name__ == '__main__':
if cube(15) != 3375:
print "Error, cube(15) is not correct"
_____________________________________________________
Jeff japhy Pinyan,
P.L., P.M., P.O.D, X.S.:
Perl,
regex,
and perl
hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
| [reply] [d/l] |
Re: Dual personality: Module and script
by bgreenlee (Friar) on Aug 03, 2004 at 15:23 UTC
|
You could also check the value of $0. If your module is executed rather than imported, it will return the name of the module. Otherwise it will return the name of the script that imported it.
Brad
| [reply] [d/l] |
|
Thank everybody for the replies.
I was looking to what user bgreenlee replied.
I do not think it is that terrible to have, on occasion and for private use, a module that is "require" as this is more similar to DLL, that can also be started from command line or "system"
Solution works like charm. If loaded as stand alone, the suffix is .pm. If 'required' then the suffix is .pl
all that is needed then
if ($0 =~ /\.pm$/i) {
# execute stand alone
)
# fall thru for module.
Thanks again for all replies.
| [reply] [d/l] |
|
| [reply] |
|
|
|
|
Re: Dual personality: Module and script
by Fletch (Bishop) on Aug 03, 2004 at 14:56 UTC
|
The Parse::RecDescent does somthing similar to this with its import mechanism to generate a precompiled dump of a grammar. You might look at what it does.
| [reply] [d/l] |
Re: Dual personality: Module and script
by fergal (Chaplain) on Aug 03, 2004 at 15:23 UTC
|
Here's a solution that works with require and use. Assuming it's saved in mod.pm
print "I'm a ".($INC{"mod.pm"} ? "module" : "script")."\n";
output is
fergal@linux:~> perl mod.pm
I'm a script
fergal@linux:~ perl -e 'require mod'
I'm a module
| [reply] [d/l] |
Re: Dual personality: Module and script
by TomDLux (Vicar) on Aug 04, 2004 at 02:30 UTC
|
I too have occassionally hidden test code in my modules, though not as cleanly as BrowserUK
In the fine tradition of TMTOWTDI, note that $0 doesn't change, but __FILE does, as you go from x.pl to x.pm, whether by 'use' or by 'require'.
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] |
|
|