如何检查perl模块是否可用?

How to check if perl module is available?

我找到了 this:

my $rc = eval
{
  require Term::ReadKey;
  Term::ReadKey->import();
  1;
};

if($rc)
{
  # Term::ReadKey loaded and imported successfully
  ...
}

但这不适用于在其他模块中定义的包,例如:

{
  package Hi::Test;
}    

my $rc =  eval{ require Hi::Test };

$rc 这里是假的。

如何检查 'Hi::Test' 是否可用?

我假设该包中确实发生了一些事情,而不仅仅是一个空块。

以下代码检查该包的符号 table 中是否有任何条目。它很脏,但只要注册了 subs 或 package 变量,它就可以工作。

{
  package Hi::Test;

  sub foo;
}

my $rc =  eval{ require Hi::Test };
if (! $rc) {
  $rc = do {
    no strict;
    *stash = *{"Hi::Test::"};
    scalar keys %stash;
  }
}

print $rc;

它将打印1

我对此有点生疏,但我认为你的 require 无论如何都会失败 - 这个错误:

#!/usr/bin/perl

{
    package Hi::Test;

    sub foo {
        print "bar\n";
    }
}

{
    package main;
    require Hi::Test; 
}

此错误 - 它无法找到它 @INC(因为它不在 @INC 中)。 userequire 都明确告诉 perl 到 "go out and find a module file"

但您仍然可以通过以下方式调用 'foo':

Hi::Test::foo();

所以你不能用 eval 测试模块的加载,也不能检查 %INC

但是你可以做的是检查 %Hi:::

use Data::Dumper;
print Dumper \%Hi::;
print Dumper \%Hi::Test::;

这给了我们:

$VAR1 = {
          'Test::' => *{'Hi::Test::'}
        };
$VAR1 = {
          'foo' => *Hi::Test::foo
        };

所以我们可以:

print "Is loaded" if defined $Hi::{'Test::'}

已更新
我找到了这条线索:

my $module =  *main::;
my @sub_name =  split '::', $full_name;
while( each @sub_name ) {
    $module =  $$module{ $sub_name[$_].'::' };
}
print "Module is available"   if $module;

答案相比,它不会在全局存储中创建额外的变量

你想要像 defined(*Hi::Test::) 这样的东西,只是简单地提到 *Hi::Test:: 就创建了包。

$ perl -E'
   say defined(*Hi::Test::) ? "exists" : "doesn'\''t exist";
'
exists

通过使用符号引用,您可以避免这个问题。

$ perl -E'
   { package Hi::Test }
   say defined(*{"Hi::Test::"}) ? "exists" : "doesn'\''t exist";
   say defined(*{"Hi::TEST::"}) ? "exists" : "doesn'\''t exist";
'
exists
doesn't exist

将该代码放入子程序中可以使事情变得更清晰。

$ perl -E'
   use strict;
   use warnings;

   sub test_for_package {
      my ($pkg_name) = @_;
      $pkg_name .= "::";
      return defined(*$pkg_name);
   }

   { package Hi::Test }
   say test_for_package("Hi::Test") ? "exists" : "doesn'\''t exist";
   say test_for_package("Hi::TEST") ? "exists" : "doesn'\''t exist";
'
exists
doesn't exist

请注意,创建包 Foo::Bar::Baz 也会创建包 FooFoo::Bar