Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
151 views
in Technique[技术] by (71.8m points)

Anyway to tell if perl script is run via do?

I have a small script configuration file which is loaded from a main script.

#main.pl
package MYPACKAGE;
our $isMaster=1;

package main;
my config=do "./config.pl"

#config.pl
my $runViaDoFlag; 

$runViaDoFlag=$0=~/main.pl/;                  #Test if main.pl is the executing script
$runViaDoFlag=defined $MYPACKAGE::isMaster;    #Test custom package variable
                                               #Is there a 'built-in' way to do this?

die "Need to run from main script! " unless $runViaDoFlag;

{
    options={
        option1=>"some value",
        option2=>"some value",
    },
    mySub=>sub { 
               # do interesting things here
           }
}

In a more complicated config file it might not be so obvious that config.pl script is intended to only be executed by do. Hence I want to include a die with basic usage instructions.

Solutions:

  • test $0 for the main script name
  • have custom package variable defined in the main script and checked by the config script
  • simply have a comment in the config instructing the user how to use it.

These work, however is there some way of knowing if a script is executed via do via built-in variable/subs?

question from:https://stackoverflow.com/questions/65660338/anyway-to-tell-if-perl-script-is-run-via-do

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I'd offer a change in design: have that configuration in a normal module, in which you can then test whether it's been loaded by (out of) the main:: namespace or not. Then there is no need for any of that acrobatics with control variables etc.

One way to do that

use warnings;
use strict;
use feature 'say';

use FindBin qw($RealBin);
use lib $RealBin;          # so to be able to 'use' from current directory

use ConfigPackage qw(load_config);

my $config = load_config();
# ...

and the ConfigPackage.pm (in the same directory)

package ConfigPackage;

use warnings;
use strict;
use feature 'say';
use Carp;

use Exporter qw();                 # want our own import
our @EXPORT_OK = qw(load_config);

sub import { 
    #say "Loaded by: ", (caller)[0];
    croak "Must only be loaded from 'main::'"
        if not ( (caller)[0] eq 'main' );

    # Now switch to Exporter::import to export symbols as needed
    goto &Exporter::import;
}

sub load_config {
    # ...
    return 'Some config-related data structure';
}

1;

(Note that this use of goto is fine.)

This is just a sketch of course; adjust, develop further, and amend as needed. If this is lodaed out of a package other than main::, and so it fails, then that happens in the compile phase, since that's when import is called. I'd consider that a good thing.

If that config code need be able to run as well, as the question may indicate, then have a separate executable that loads this module and runs what need be run.


As for the question as stated, the title and the question's (apparent) quest differ a little, but both can be treated by using caller EXPR. It won't be a clean little "built-in" invocation though.

The thing about do as intended to be used is that

do './stat.pl' is largely like

eval `cat stat.pl`;

except that ...

(That stat.pl is introduced earlier in docs, merely to signify that do is invoked on a file.)

Then caller(0) will have clear hints to offer (see docs). It returns

my ($package, $filename, $line, $subroutine, $hasargs,
    $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
= caller($i);

In a call asked for, do './config.pl', apart from main (package) and the correct filename, the caller(0) in config.pl also returns:

  • (eval) for $subroutine

  • ./config.pl for $evaltext

  • 1 for $is_require

Altogether this gives plenty to decide whether the call was made as required.

However, I would not recommend this kind of involved analysis instead of just using a package, what is also incomparably more flexible.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...