I want to use an external library in the BEGIN
block of a Perl script.
The first test which I did was to check whether my @INC
is getting popullated if I push some values:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
}
Which works as expected and shows:
$VAR1 = 'D:/perl/5163/site/lib';
$VAR2 = 'D:/perl/5163/lib';
$VAR3 = '.'; # I am not sure about this one?!
$VAR4 = 'd:/external_pm/';
Now I want to import a module right after the push
:
use strict;
use warnings;
BEGIN {
push @INC, "d:/external_pm/";
use Data::Dumper;
print Dumper @INC;
use ExtScript;
}
The error which follows is showing me that @INC
was not updated:Can't locate ExtScript.pm in @INC (@INC contains: D:/perl/5163/site/lib
D:/perl/5163/lib .) at file.pl line 9.
BEGIN failed--compilation aborted at file.pl line 9.
Why the @INC
it's not updating?
I can't import a module in the BEGIN
block? Or is a missusage of Perl?
use
statements are executed at compile time (specifically, during the BEGIN phase), whereas normal code is run later. Let's look at this simplified snippet:
BEGIN {
push @INC, "some/dir";
use Example;
}
If we spell out all phases explicitly, that would be equivalent to:
BEGIN {
push @INC, "some/dir";
BEGIN { require Example; Example->import() }
}
So the Example
module will be imported before the push
runs.
There are a number of ways to address this.
The simplest way is to put only the @INC
manipulation into a BEGIN block, and import the module outside:
BEGIN { push @INC, "some/dir" }
use Example;
A better solution is to use the lib
pragma to handle @INC
:
use lib "some/dir";
use Example;
However, there is a major difference: use lib
puts additional directories at the beginning of the module search path, so you may accidentally override other modules. push @INC
only adds directories to the end, as a fallback if a module wasn't found in other locations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With