列出所有已加载/定义(未安装)的包

T-B*_*ull 5 perl

请在回答之前仔细阅读这个问题,这个问题经常被误解。

我需要一种方法来检查当前解释器中是否存在特定包。我想可能有一种方法可以列出所有已加载的包,以便我可以在该列表中进行搜索。让我们举个例子。这是一个简单的脚本,定义了几个包:

#!/path/to/perl

package Foo;

# some code in package Foo

package Bar;

# some code in package Bar

package main;

# main program. Want to have a list which includes 'Foo' and 'Bar'
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,这里没有useor require。这才是重点。我不是在寻找系统上安装的模块(可以通过 traversing 列出这些模块@INC)。我也不寻找已被删除的模块require(那些在 中列出%INC)。我想要一个运行时可用的列表,即已使用package语句定义的包。我想这相当于谈论已定义的名称空间列表。

这有什么好处呢?

事情是这样的。在一个相当大的项目中,我经常发现自己重构模块的结构。这包括移动或重命名模块/包。将模块从Util::Foo重命名为 时Util::Bar,必须完成 3 件事。

  • 将模块Util/Foo.pm从重命名为Util/Bar.pm
  • 将包语句从 修改package Util::Foo;package Util::Bar;
  • use条款从更改use Util::Foo;use Util::Bar;

如果我执行步骤 1 和 3,但忘记修改 package 语句,则会加载模块,但未定义Util::Bar包。Util::Bar相反,Util::Foo包仍然是已定义的。这会导致运行脚本时出现奇怪的、难以理解的警告/错误。Perl 不会指出明显的错误,因为在另一个名称的模块中定义包在 Perl 中是完全合法的。

我遇到的另一个奇怪的情况是,当我在子句中出现区分大小写的错误时use。如果我有一个FooBar正确定义了 package 的模块FooBar,但我是usemodule/package Foobar(小写 b),我会在 Unix 系统上立即收到错误,因为找不到模块文件,但在 Windows 系统上,模块文件成立。如果我由于复制和粘贴而继续使用错误的包名称,则会出现难以追踪的方法未找到错误。同样,在这种情况下,我在超类的重写方法方面遇到了奇怪的错误。

Leo*_*erd 5

遍历符号表。

从 开始%::并查看名称本身以 结尾的所有键::,然后递归。


Sin*_*nür 3

使用Devel::Symdump

require Devel::Symdump;
@packs = qw(some_package another_package);
$obj = Devel::Symdump->new(@packs);        # no recursion
$obj = Devel::Symdump->rnew(@packs);       # with recursion
# Methods
@array = $obj->packages;
@array = $obj->scalars;
@array = $obj->arrays;
@array = $obj->hashes;
@array = $obj->functions;
@array = $obj->filehandles;  # deprecated, use ios instead
@array = $obj->dirhandles;   # deprecated, use ios instead
@array = $obj->ios;
@array = $obj->unknowns;     # only perl version < 5.003 had some
Run Code Online (Sandbox Code Playgroud)