Динмически загружать модули в perl - PullRequest
0 голосов
/ 04 февраля 2020

Я хочу, чтобы множество функций хранилось в папке и включало их в основной скрипт.

Например, у меня есть эта библиотека ABC1.pm:

package ABC1;

use strict;
use warnings;

my $var1 = 'abc1';

sub func1 {
    print "$var1\n";
}

return 1;

Еще одна называется ABC2.pm:

package ABC2;

use strict;
use warnings;

my $var2 = 'abc2';

sub func2 {
    print "$var2\n";
}

return 1;

Оба файла сохраняются в папке библиотеки Теперь я запускаю основной скрипт, который просматривает папку со всеми находящимися внутри файлами и пытается загрузить их:

#!/usr/bin/env perl
#script.pl

use strict;
use warnings;
BEGIN {push @INC, './libraries/.'}
# use ABC1;
# use ABC2;

my $dir = './libraries';
my @libraries;
opendir(DIR, $dir) or die $!;
while (my $file = readdir(DIR)) {
    next if ($file =~ m/^\./);
    print "$file\n";
    $file =~ s/\.pm$//;
    print "$file\n";
    push @libraries, $file;
}

eval {
    foreach my $library (@libraries){
        require $library;
        $library->import();
    }
    1;
} or do {
   my $error = $@;
   print $error;
};

ABC1->func1();
ABC2->func2();

Если я просто запускаю его с использованием введенного вручную статута использования, он работает. Но если я хочу использовать фрагмент кода, который не прокомментирован, я получаю следующую ошибку:

Невозможно найти ABC1 в @ IN C (@ IN C содержит: C: / Strawberry / perl / site / lib / MSWin32-x64-multi-thread C: / Strawberry / perl / site / lib C: / Strawberry / perl / vendor / lib C: / Strawberry / perl / lib. ./libraries/. ./libraries/.) в строке ab c .pl 25. Не удается найти метод объекта "func1" через пакет "ABC1" (возможно, вы забыли загрузить "ABC1"?) в ab c .pl строка 34.

Но библиотеки путей отображаются в @ IN C, поэтому я не понимаю, что происходит.

1 Ответ

2 голосов
/ 04 февраля 2020

Хотя use MODULE и require MODULE ожидают имя модуля, синтаксис require EXPR для require ожидает путь к файлу.

Это может быть путь относительно пути в @INC.

require "Foo/Bar.pm";

Это может быть путь относительно текущего каталога.

require "./Foo/Bar.pm";

Это может быть абсолютный путь.

require "/some/dir/Foo/Bar.pm";

Исправлено и убрано:

#!/usr/bin/env perl

use strict;
use warnings;

use FindBin qw( $RealBin );  # Get the location of this program.

my $plugins_dir_qfn = "$RealBin/libraries";

my @libraries;
opendir(my $dh, $plugins_dir_qfn) or die $!;
while (my $fn = readdir($dh)) {
    next if $fn =~ /^\./ || $fn !~ /\.pm\z/;

    my $qfn = "$plugins_dir_qfn/$fn";
    #print "$qfn\n";

    eval { require $qfn; }
        or warn("Can't load \"$qfn\": $@");
}

ABC1->func1();
ABC2->func2();
...