T-Bull
T-Bull

Reputation: 2146

List all packages which are loaded/defined (not installed)

Please read this question carefully before replying, it is often misunderstood.

I need a way to check if a particular package exists in the current interpreter. I figured there might be a way to list all loaded packages, so that I can search in that list. Let's have an example. This is a simple script which defines several packages:

#!/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'

As you can see, there's no use or require here. That's the point. I'm not looking for the modules installed on my system (those can be listed by traversing @INC). Nor do I look for the modules that have been required (those are listed in %INC). I want to have a list of packages which are available to the runtime, i.e. which have been defined with a package statement. I guess it's equivalent to speak of a list of defined namespaces.

What could this be good for?

The thing is this. In a rather large project I often find myself refactoring the structure of my modules. That includes moving or renaming modules/packages. When renaming a module from Util::Foo to Util::Bar, 3 things have to be done.

If I do steps 1 and 3, but forget to modify the package statement, the module Util::Bar is loaded, but the package Util::Bar is not defined. Rather, the Util::Foo package is still defined. That leads to strange, incomprehensible warnings/errors when running the script. Perl won't point to the obvious error because defining a package within a module of another name is perfectly legal in Perl.

Another oddity I came across is when I have a case-sensitivity mistake in the use clause. If I have a module FooBar which correctly defines the package FooBar, but I use the module/package Foobar (lowercase b), I get an instant error on a Unix system, because the module file is not found, but on a Windows system, a module file is found. If I then continue to use the wrong package name due to copy&paste, method-not-found errors arise which are hard to track down. Similarly, I had strange errors with respect to overridden methods from a superclass in a situation like this.

Upvotes: 6

Views: 401

Answers (2)

LeoNerd
LeoNerd

Reputation: 8532

Walk the symbol table.

Start from %:: and look at all keys whose names themselves end in ::, and recurse.

Upvotes: 6

Sinan Ünür
Sinan Ünür

Reputation: 118118

Use 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

Upvotes: 4

Related Questions