如何使用仅在运行时已知的 Perl 包?

发布于 2024-07-11 14:44:13 字数 211 浏览 7 评论 0原文

我有一个 Perl 程序,需要使用包(我也编写)。 其中一些包仅在运行时选择(基于某些环境变量)。 当然,我不想在代码中为所有这些包添加一个“use”行,但只有一个基于此变量的“use”行,例如:

use $ENV{a};

不幸的是,这当然不起作用。 关于如何做到这一点有什么想法吗?

提前致谢, 奥伦

I have a Perl program, that needs to use packages (that I also write). Some of those packages are only chosen in Runtime (based on some environment variable). I don't want to put in my code a "use" line for all of those packages, of course, but only one "use" line, based on this variable, something like:

use $ENV{a};

Unfortunately, this doesn't work, of course. Any ideas on how to do this?

Thanks in advance,
Oren

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

誰認得朕 2024-07-18 14:44:13
eval "require $ENV{a}";

use”在这里效果不佳,因为它仅在 eval 的上下文中导入。

正如@Manni 所说,实际上,最好使用 require。 引用自 man perlfunc

If EXPR is a bareword, the require assumes a ".pm" extension and 
replaces "::" with "/" in the filename for you, to make it easy to 
load standard modules.  This form of  loading of modules does not 
risk altering your namespace.

In other words, if you try this:

        require Foo::Bar;    # a splendid bareword

The require function will actually look for the "Foo/Bar.pm" file 
in the directories specified in the @INC array.

But if you try this:

        $class = 'Foo::Bar';
        require $class;      # $class is not a bareword
    #or
        require "Foo::Bar";  # not a bareword because of the ""

The require function will look for the "Foo::Bar" file in the @INC 
array and will complain about not finding "Foo::Bar" there.  In this 
case you can do:

        eval "require $class";
eval "require $ENV{a}";

"use" doesn't work well here because it only imports in the context of the eval.

As @Manni said, actually, it's better to use require. Quoting from man perlfunc:

If EXPR is a bareword, the require assumes a ".pm" extension and 
replaces "::" with "/" in the filename for you, to make it easy to 
load standard modules.  This form of  loading of modules does not 
risk altering your namespace.

In other words, if you try this:

        require Foo::Bar;    # a splendid bareword

The require function will actually look for the "Foo/Bar.pm" file 
in the directories specified in the @INC array.

But if you try this:

        $class = 'Foo::Bar';
        require $class;      # $class is not a bareword
    #or
        require "Foo::Bar";  # not a bareword because of the ""

The require function will look for the "Foo::Bar" file in the @INC 
array and will complain about not finding "Foo::Bar" there.  In this 
case you can do:

        eval "require $class";
暮年慕年 2024-07-18 14:44:13

“use”语句在编译时运行,而不是在运行时运行。 您将需要需要您的模块:

my $module = "Foo::Bar";
eval "require $module";

"use" Statements are run at compilation time, not at run time. You will need to require your modules instead:

my $module = "Foo::Bar";
eval "require $module";
海夕 2024-07-18 14:44:13

我会使用UNIVERSAL::require。 它具有 requireuse 方法来使用包。 use 方法还将调用包的import

use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package:  ' . $@;

I would use UNIVERSAL::require. It has both require and use methods to use a package. The use method will also call import for the package.

use UNIVERSAL::require;
$ENV{a}->use or die 'Could not import package:  ' . $@;
柒七 2024-07-18 14:44:13

如果您不希望在编译时发生这种情况,您可能需要使用 require 而不是 use,然后手动导入您可能需要的任何符号。 请参阅此 Perl Cookbook 链接(来自 Google 图书),详细讨论了可用于实现所需目标的方法。

You probably want to use require instead of use if you don't want it to happen at compile time, and then manually import any symbols you might need. See this link to the Perl Cookbook (from Google Books) for a good discussion of methods you can use to achieve what you want.

琴流音 2024-07-18 14:44:13

我认为在运行时加载的模块可以是插件。 我遇到这种问题,在某些情况下有特定的模块,这些模块在运行时作为插件加载 模块::Pluggable

也许您需要更改模块的逻辑,但它的工作原理和扩展性非常好(我的应用程序从四个模块开始,现在有二十个,而且还在不断增长)。

I think that a module loaded in runtime can be a Plugin. I have this kind of problem, having specific modules to some cases that are loaded in run time as plugins with Module::Pluggable.

Maybe you need to change the logic of your modules, but it works and scale very well (my app started with four modules and now have twenty and it's growing).

晚风撩人 2024-07-18 14:44:13

如何使用核心模块 Module::Load

以您的示例:

use Module::Load;
load $ENV{a};

“Module::Load - 模块和文件的运行时要求”

“加载消除了知道您是否试图要求文件或模块的需要。”

如果失败,它将因类似“无法在 @INC 中定位 xxx(@INC 包含:...”)而终止。

How about using the core module Module::Load

With your example:

use Module::Load;
load $ENV{a};

"Module::Load - runtime require of both modules and files"

"load eliminates the need to know whether you are trying to require either a file or a module."

If it fails it will die with something of the like "Can't locate xxx in @INC (@INC contains: ...".

八巷 2024-07-18 14:44:13

许多年后,eval "use $mod_name"; 似乎工作得很好(至少从 5.8.8 开始)。

相对于eval "require $mod_name";的优点是加载模块的默认导出是自动导入的; 换句话说:

eval "use $mod_name";

的缩写形式

eval "require $mod_name"; ; $mod_name->import();

这是一个测试命令,它通过 env 传递模块的名称。 变量 mod_name,加载并导入模块,然后使用导入的函数(假设有一个类似 POSIX 的 shell):

 $ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
 $VAR1 = 'hi!';

我可能会遗漏一些细节; 如果是这样,请告诉我。

Many years later, eval "use $mod_name"; seems to work just fine (as of at least 5.8.8).

The advantage over eval "require $mod_name"; is that the loaded module's default exports are automatically imported; in other words:

eval "use $mod_name";

is the shorter equivalent of

eval "require $mod_name"; $mod_name->import();

Here's a test command, which passes the name of the module via env. variable mod_name, loads and imports the module, then uses an imported function (assumes a POSIX-like shell):

 $ mod_name='Data::Dumper' perl -e 'eval "use $ENV{mod_name}"; print Dumper("hi!")'
 $VAR1 = 'hi!';

I may be missing subtleties; if so, please let me know.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文