2010-06-04 1 views
0

У меня есть структура каталогов, которая выглядит следующим образом:Как я могу динамически обнаружить пакеты из частичного пространства имен в perl?

Foo :: Bar :: Baz :: 1 Foo :: Bar :: Баз :: 2 и т.д.

Могу ли я получить список пакетов, от чего-то вроде:

use Foo::Bar::Baz;

Спасибо!

Редактировать: Улучшилось, что такое модули.

ответ

0

Просто чтобы быть ясно, что вы ищете на случайных пакетов в случайном коде Perl?

или для Perl модулей, т.е. "a/b/c/d1.pm" с модулем "a :: b :: c :: d1"?

В любом случае вы не можете использовать один оператор «use», чтобы загрузить их все.

Что вам нужно сделать, это найти все подходящие файлы, используя либо glob, либо File::Find.

В первом случае (модули), вы можете загрузить их либо require -ный каждый файл, или путем преобразования файла в имя модуля (s#/#::#g; s#\.pm$##;) и вызов use на каждый модуль по отдельности.

Насколько фактические пакеты, вложенные в случайных Perl файлов, эти пакеты могут быть:

  • Включенный в список по оглавлению каждый файл (снова, найденный через glob или File::Find) для /^package (.*);/

  • На самом деле загружается выполнив require $file для каждого файла.

    В этом случае, обратите внимание, что имя пакета для каждого из этих пакетов в a/b/c/1.pl будет НЕ должны быть связаны с «A :: B :: гр» - например, они могут быть названы автором файла «p1», «a :: p1» или «a :: b :: c :: p1_something».

1

Обычно сценарий, такой как a/b/c.pl, не имеет пространства имен, кроме main. Возможно, вы думаете об обнаружении модулей с именами, такими как a/b/c.pm (что плохое имя, так как имена пакетов с наименьшими именами обычно зарезервированы для внутренних элементов Perl).

Однако данный путь к каталогу, вы можете искать потенциальных модулей Perl с использованием File::Find:

use strict; 
use warnings; 
use File::Find; 
use Data::Dumper; 

my @modules; 
sub wanted 
{ 
    push @modules, $_ if m/\.pm$/ 
} 
find(\&wanted, 'A/B'); 

print "possible modules found:\n"; 
print Dumper(\@modules)' 
7

Если вы хотите, чтобы загрузить все модули в вашем включают пути с определенным префиксом (например, все под a::b::c, вы можете использовать Module::Find.

Например:

use Module::Find 'useall'; 

my @loaded = useall 'Foo::Bar::Baz'; # loads everything under Foo::Bar::Baz 

Это зависит от вашей @INC пути создаются с необходимыми каталогами, так что все требуемые манипуляции (например, с use lib) первым.

1

Это может быть излишним, но вы можете проверить таблицу символов до и после загрузки модуля и посмотреть, что изменилось:

use strict; use warnings; 
my %original = map { $_ => 1 } get_namespaces("::"); 
require Inline; 
print "New namespaces since 'require Inline' call are:\n"; 
my @new_namespaces = sort grep !defined $original{$_}, get_namespaces("::"); 
foreach my $new_namespace (@new_namespaces) { 
    print "\t$new_namespace\n"; 
} 

sub get_namespaces { 
    # recursively inspect symbol table for known namespaces 
    my $pkg = shift; 
    my @namespace =(); 
    my %s = eval "%" . $pkg; 
    foreach my $key (grep /::$/, keys %s) { 
    next if $key eq "main::"; 
    push @namespace, "$pkg$key", get_namespaces("$pkg$key"); 
    } 
    return @namespace; 
} 

 
New namespaces since 'require Inline' call are: 
     ::AutoLoader:: 
     ::Config:: 
     ::Digest:: 
     ::Digest::MD5:: 
     ::Dos:: 
     ::EPOC:: 
     ::Exporter:: 
     ::Exporter::Heavy:: 
     ::File:: 
     ::File::Spec:: 
     ::File::Spec::Cygwin:: 
     ::File::Spec::Unix:: 
     ::File::Spec::Win32:: 
     ::Inline::Files:: 
     ::Inline::denter:: 
     ::Scalar:: 
     ::Scalar::Util:: 
     ::Socket:: 
     ::VMS:: 
     ::VMS::Filespec:: 
     ::XSLoader:: 
     ::vars:: 
     ::warnings::register:: 

 Смежные вопросы

  • Нет связанных вопросов^_^