如何在perl中从部分命名空间动态发现包?

时间:2010-06-04 16:37:39

标签: perl packages autodiscovery

我的目录结构如下:

富::酒吧::巴兹:: 1 Foo :: Bar :: Baz :: 2等

我可以列出以下内容的包:

use Foo::Bar::Baz;

谢谢!

编辑:更清楚模块是什么。

4 个答案:

答案 0 :(得分: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 :(得分:1)

通常,诸如/ b / c.pl之类的脚本不具有main以外的命名空间。也许您正在考虑使用诸如a / b / c.pm之类的名称来发现 modules (这是一个坏名称,因为通常为Perl内部保留较低的包名称。)

但是,给定目录路径,您可以使用File::Find查找潜在的 Perl模块:

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)'

答案 2 :(得分: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::

答案 3 :(得分:0)

为了清楚起见,您是否在随机Perl代码中查看随机包?

或Perl 模块,例如模块“a :: b :: c :: d1”的“a / b / c / d1.pm”?

在任何一种情况下,您都不能使用单个“use”语句来加载它们。

您需要做的是使用globFile::Find找到所有相应的文件。

在第一种情况(模块)中,您可以通过require - 每个文件加载它们,或者通过将文件名转换为模块名称(s#/#::#g; s#\.pm$##;)并调用use来加载它们每个模块都是单独的。

对于嵌套在随机Perl文件中的实际包,这些包可以是:

  • 通过点击每个文件(再次通过globFile::Find找到)列出/^package (.*);/

  • 实际上是通过为每个文件执行require $file来加载的。

    在这种情况下,请注意a/b/c/1.pl中每个软件包的软件包名称 NOT 需要与“a :: b :: c”相关 - 例如它们可以由文件作者“p1”,“a :: p1”或“a :: b :: c :: p1_something”命名。