Re: Was my module used or required?
by PodMaster (Abbot) on Dec 06, 2002 at 09:22 UTC
|
#moo.pm
package moo;
BEGIN {
warn "moo ".join'',caller(1);
}
sub import {
warn "import ".join'',caller(1);
}
1;
__END__
E:\new>perl -e"use moo;"
moo mainmoo.pm5(eval)000 at moo.pm line 4.
import mainmoo.pm1main::BEGIN100 at moo.pm line 8.
E:\new>perl -e"require moo;"
moo mainmoo.pm5(eval)000 at moo.pm line 4.
MJD says you
can't just make shit up and expect the computer to know what you mean, retardo!
** The Third rule of perl club is a statement of fact: pod is sexy.
|
| [reply] [Watch: Dir/Any] [d/l] |
|
Sorry to be so "silly", but...
If my module get's conditionally require'd inside an eval() then the BEGIN block in my module won't be executed when the application starts it's execution which is what I'm trying to verify.
Update:
I read below: "...the moment it is completely defined ..." which corresponds to my understanding.
Doesn't this mean that an eval("require MyModule") will make sure that MyModule get's parsed in this very moment instead of during compilation of the main script?
If this is so, then any BEGIN block in MyModule will be parsed and executed at eval() time. No?
If this is not so, but all modules are parsed at compile time even if they are only conditionally required in an eval() statement, how can it be that modules that are not at all available on the system will not create a compilation error as long as the condition is not met and the module is not being actually required?
And how does perl handle when I read in from a database what module to conditionally require in an eval() statement?
(Where the name of the module does not ever appear in my code, but only in a variable brought in from the database.)
Everything went worng, just as foreseen.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Always means alway, well ;)
from perldoc perlmod
Package Constructors and Destructors
Four special subroutines act as package constructors and destructors.
These are the BEGIN, CHECK, INIT, and END routines. The
sub is optional for these routines.
A BEGIN subroutine is executed as soon as possible, that is, the moment
it is completely defined, even before the rest of the containing file
is parsed. You may have multiple BEGIN blocks within a file--they
will execute in order of definition. Because a BEGIN block executes
immediately, it can pull in definitions of subroutines and such from other
files in time to be visible to the rest of the file. Once a BEGIN
has run, it is immediately undefined and any code it used is returned to
Perl's memory pool. This means you can't ever explicitly call a BEGIN.
An END subroutine is executed as late as possible, that is, after
perl has finished running the program and just before the interpreter
is being exited, even if it is exiting as a result of a die() function.
(But not if it's polymorphing into another program via exec, or
being blown out of the water by a signal--you have to trap that yourself
(if you can).) You may have multiple END blocks within a file--they
will execute in reverse order of definition; that is: last in, first
out (LIFO). END blocks are not executed when you run perl with the
-c switch, or if compilation fails.
Inside an END subroutine, $? contains the value that the program is
going to pass to exit(). You can modify $? to change the exit
value of the program. Beware of changing $? by accident (e.g. by
running something via system).
Similar to BEGIN blocks, INIT blocks are run just before the
Perl runtime begins execution, in ``first in, first out'' (FIFO) order.
For example, the code generators documented in perlcc make use of
INIT blocks to initialize and resolve pointers to XSUBs.
Similar to END blocks, CHECK blocks are run just after the
Perl compile phase ends and before the run time begins, in
LIFO order. CHECK blocks are again useful in the Perl compiler
suite to save the compiled state of the program.
When you use the -n and -p switches to Perl, BEGIN and
END work just as they do in awk, as a degenerate case.
Both BEGIN and CHECK blocks are run when you use the -c
switch for a compile-only syntax check, although your main code
is not.
MJD says you
can't just make shit up and expect the computer to know what you mean, retardo!
** The Third rule of perl club is a statement of fact: pod is sexy.
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
"Why would you care?"
I'd like to know if a BEGIN block in my module is executed in the beginning of the applications execution or if it's executed later on, as a result of the module being require'd.
perldoc.com seems to have a temporary outage on the search facility. I've read the Camel but not found what I was looking for. Just hoped someone could tell me what I missed. ;-)
caller and the node you referenced to talks about how a method is called. I need to know if my module was loaded in compile time or during run time.
Thanks anyway.
Everything went worng, just as foreseen.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
If you know about BEGIN{} blocks you should also know that there is not two separate compile and runtime phases. These two are interleaved. Even if neither you nor the module authors use any BEGIN blocks!
I'm afraid you'll have to rethink this. Consider this:
#!/usr/bin/perl
BEGIN {
push @INC, '/some/directory';
require Your::Module;
}
...
This way your module is being included as soon as at all possible, yet it's require()d, not use()d.
If you tell us what and why do you want to do differently we can come up with something. Just now my only idea is to set a variable when the script "starts". $My::Module::Runtime=1 is probably the best you can get.
Jenda | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Was my module used or required?
by strat (Canon) on Dec 06, 2002 at 11:42 UTC
|
I don't know a proper way either, just two dirty ones which may or may not work.
Is it possible to find out where BEGIN was called from by the function caller() ? If yes, there may be a value (filename from (caller())[1] and line number from (caller())[2] ) and you could parse the file around the line. But I don't know if this works with BEGIN-Blocks.
Here another dirty idea for longer running programs: there exists a perl variable called $^T (=$BASETIME) which contains the unix epoch time when the program was started. If the module was "used", this will be about the same as a timestamp in the Module's BEGIN-block, and may be earlier if the module is required later at runtime.
Sorry!
Best regards,
perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32" | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Was my module used or required?
by grantm (Parson) on Dec 06, 2002 at 10:13 UTC
|
| [reply] [Watch: Dir/Any] |
|
Excelent point, but only if my module would be a 'traditional' module using the Exporter.
This is an OO module. No export, no import. (Unless I've misunderstood something fundamental again. ;-)
Sorry I didn't mention that in my original post.
Everything went worng, just as foreseen.
| [reply] [Watch: Dir/Any] |
|
You've probably already figured this out based on earlier answers, but the import() method is invoked regardless of whether you choose to inherit it from the Exporter module or not. In addition, there's no reason it has to actually import anything. In this sense, it's simply a hook you can use for anything you want when your module is invoked with use. Fear not for the sanctity of your OO model.
Matt
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Was my module used or required?
by Anonymous Monk on Dec 06, 2002 at 23:29 UTC
|
Some test code expanding on Jenda's suggestion, partially to satisfy my own curiosity. Interesting problem, hope this is of some help - its rough.
A runtime flag in caller() lets your module evaluate at what stage it is being compiled...
package amIBeingUsed; # in amIBeingUsed.pm
if(defined( ${ caller()."::RUNTIME_OK" } ))
{
# the flag is set
print "what took you so long to call me?";
}
else
{
# still compiling
print "eurgh, i feel so cheap!";
}
sub import
{
print " slap!!!\n";
}
1;
...meanwhile, at the Bat Cave ...
use strict;
my $module = "amIBeingUsed";
our $RUNTIME_OK = 1;
# possible scenarios
use amIBeingUsed; # "eurgh, i feel so cheap! slap!!!"
eval "use $module"; # "what took you so long to call me? slap!!!"
require amIBeingUsed; # "what took you so long to call me?"
eval "require $module"; # "what took you so long to call me?"
| [reply] [Watch: Dir/Any] [d/l] [select] |