Вызов script с тем же @INC, что и родительский script
Я хочу вызвать внешний script с помощью system ($script)
или do $script
. В моем @INC у меня есть некоторые определенные модули, которые я импортирую. Как я могу вызвать $script
и передать ему тот же @INC
?
Script1.pm
#importing some libs
#code
$script = "path_to_script";
system ($script);
Script2.pm
use [email protected];
И я получаю сообщение об ошибке:
Невозможно найти LibFromScript1 в @INC...
Ответы
Ответ 1
Самый простой способ - установить переменную среды PERL5LIB
. Это добавит список каталогов в дочерний процесс @INC
array
Ваш код выглядел бы как
$ENV{PERL5LIB} = join ':', @INC;
system $script;
Это имеет тот недостаток, что стандартные каталоги также будут добавлены в @INC
. Это не должно вызывать никаких проблем, но было бы лучше установить PERL5LIB
только в пользовательские каталоги, если вы их знаете в этот момент.
Обратите внимание, что perl будет игнорировать PERL5LIB
, если вы работаете под флагом taint.
Ответ 2
Строго отвечая на ваш вопрос, вы могли бы do $script;
, хотя рекомендуемый способ состоял бы в том, чтобы разделить вашу общую программную логику на модуль и use/require
.
Ответ 3
Вы можете использовать Storable для сохранения @INC
в файле, а затем выбрать его в другом script.
Например, вы можете сделать что-то вроде ниже.
test.pl
#!/usr/bin/perl
use strict;
use warnings;
use Storable;
store (\@INC, "test2.dump") or die "could not store";
system("perl", "test2.pl", $$) == 0 or die "error";
test2.pl
#!/usr/bin/perl
use strict;
use warnings;
use Storable;
use Data::Dumper;
my $parentpid = shift;
my $ref = retrieve("test2.dump") or die "couldn't retrieve";
print Dumper $ref;
Как только вы получите @INC
в test2.pl
как $ref
, вы можете изменить @INC
в test2.pl
, чтобы взять содержимое из $ref
.
Ответ 4
Вопрос о том, как использовать одни и те же модули в нескольких сценариях. Координация их @INC
составляет лишь половину проблемы, и я бы предложил использовать PERL5LIB
, как в ответе Бородина. Затем те же модули также должны быть загружены в оба сценария.
Для этого мы можем написать модуль утилиты, который загружает все эти общие модули, а затем просто use
в обеих программах. Это непросто сделать правильно, но для него есть хороший модуль, Import:: Into
Файл CommonModules.pm
package CommonModules;
use warnings;
use strict;
use feature ':5.10';
use Import::Into;
sub import
{
my ($package, @args) = @_; # can pass arguments normally
my $target = caller;
warnings->import::into($target);
strict ->import::into($target);
feature ->import::into($target, ':5.10');
Getopt::Long->import::into($target);
Const::Fast ->import::into($target);
List::Util ->import::into($target, qw(max));
}
1;
Затем в скриптах вы можете сказать use CommonModules;
, и все они будут загружены с правильными импортами и рядом других сложных вещей. Он работает для прагм, модулей, классов.
Это пример с голубыми костями. В качестве аргументов можно использовать аргументы типа use CommonModules qw(base ...);
и import
для управления различными группами пакетов на основе этих аргументов. С этим можно многое сделать. См. Документы и Блог Friedman.