I need to dynamically include a Perl module, but if possible would like to stay away from eval due to work coding standards. This works:
我需要动态地包含一个Perl模块,但是如果可能的话,由于工作编码标准,我希望远离eval。这有效:
$module = "My::module";
eval("use $module;");
But I need a way to do it without eval
if possible. All google searches lead to the eval
method, but none in any other way.
但是如果可能的话,我需要一种没有eval的方法。所有谷歌搜索都会导致eval方法,但没有任何其他方式。
Is it possible to do it without eval
?
没有评估可以做到吗?
6 个解决方案
#1
44
Use require
to load modules at runtime. It often a good idea to wrap this in a block (not string) eval
in case the module can't be loaded.
使用require在运行时加载模块。如果无法加载模块,通常最好将其包装在一个块(而不是字符串)eval中。
eval {
require My::Module;
My::Module->import();
1;
} or do {
my $error = $@;
# Module load failed. You could recover, try loading
# an alternate module, die with $error...
# whatever's appropriate
};
The reason for the eval {...} or do {...}
syntax and making a copy of $@
is because $@
is a global variable that can be set by many different things. You want to grab the value as atomically as possible to avoid a race condition where something else has set it to a different value.
eval {...}或do {...}语法以及制作$ @的副本的原因是因为$ @是一个可以由许多不同的东西设置的全局变量。您希望尽可能原子地获取值,以避免竞争条件,其他东西已将其设置为不同的值。
If you don't know the name of the module until runtime you'll have to do the translation between module name (My::Module) and file name (My/Module.pm) manually:
如果您在运行时之前不知道模块的名称,则必须手动执行模块名称(My :: Module)和文件名(My / Module.pm)之间的转换:
my $module = 'My::Module';
eval {
(my $file = $module) =~ s|::|/|g;
require $file . '.pm';
$module->import();
1;
} or do {
my $error = $@;
# ...
};
#2
16
How about using the core module Module::Load
如何使用核心模块Module :: Load
With your example:
用你的例子:
use Module::Load;
my $module = "My::module";
load $module;
"Module::Load - runtime require of both modules and files"
“Module :: Load - 运行时需要模块和文件”
"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: ...".
如果它失败了它会死于类似“无法在@INC中找到xxx(@INC包含:......”)。
#3
10
Well, there's always require
as in
好吧,总是要求如此
require 'My/Module.pm';
My::Module->import();
Note that you lose whatever effects you may have gotten from the import
being called at compile time instead of runtime.
请注意,在编译时调用导入而不是运行时,可能会丢失可能产生的任何影响。
Edit: The tradeoffs between this and the eval way are: eval lets you use the normal module syntax and gives you a more explicit error if the module name is invalid (as opposed to merely not found). OTOH, the eval way is (potentially) more subject to arbitrary code injection.
编辑:这与eval方式之间的权衡是:eval允许您使用普通模块语法,如果模块名称无效(而不是仅仅找不到),则会给出更明确的错误。 OTOH,eval方式(可能)更容易受到任意代码注入。
#4
4
No, it's not possible to without
eval
, as
require()
needs the bareword module name, as described at
perldoc -f require. However, it's not an evil use of eval, as it doesn't allow injection of arbitrary code (assuming you have control over the contents of the file you are
require
ing, of course).
不,没有eval是不可能的,因为require()需要裸字模块名称,如perldoc -f require所述。但是,它并不是eval的恶意用法,因为它不允许注入任意代码(假设您可以控制所需文件的内容,当然)。
EDIT: Code amended below, but I'm leaving the first version up for completeness.
编辑:下面修改了代码,但我要完成第一个版本。
I use
I used to use this little sugar module to do dynamic loads at runtime:
我使用我曾经使用这个小糖模块在运行时进行动态加载:
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our @EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports);
sub requireClass
{
my ($class) = @_;
eval "require $class" or do { die "Ack, can't load $class: $@" };
}
1;
PS. I'm staring at this definition (I wrote it quite a while ago) and I'm pondering adding this: $class->export_to_level(1, undef, @imports);
... it should work, but is not tested.
PS。我正在盯着这个定义(我很久以前写过)而且我正在考虑添加这个:$ class-> export_to_level(1,undef,@ import); ...它应该可以工作,但是没有经过测试。
EDIT: version 2 now, much nicer without an eval (thanks ysth): :)
编辑:现在版本2,没有评估更好(感谢ysth)::)
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our @EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports);
sub requireClass
{
my ($class) = @_;
(my $file = $class) =~ s|::|/|g;
$file .= '.pm';
require $file; # will die if there was an error
}
1;
#5
1
Class::MOP on CPAN has a load_class method for this: http://metacpan.org/pod/Class::MOP
CPAN上的Class :: MOP有一个load_class方法:http://metacpan.org/pod/Class :: Male
#6
0
i like doing things like..
我喜欢做像......
require Win32::Console::ANSI if ( $^O eq "MSWin32" );
需要Win32 :: Console :: ANSI if($ ^ O eq“MSWin32”);
#1
44
Use require
to load modules at runtime. It often a good idea to wrap this in a block (not string) eval
in case the module can't be loaded.
使用require在运行时加载模块。如果无法加载模块,通常最好将其包装在一个块(而不是字符串)eval中。
eval {
require My::Module;
My::Module->import();
1;
} or do {
my $error = $@;
# Module load failed. You could recover, try loading
# an alternate module, die with $error...
# whatever's appropriate
};
The reason for the eval {...} or do {...}
syntax and making a copy of $@
is because $@
is a global variable that can be set by many different things. You want to grab the value as atomically as possible to avoid a race condition where something else has set it to a different value.
eval {...}或do {...}语法以及制作$ @的副本的原因是因为$ @是一个可以由许多不同的东西设置的全局变量。您希望尽可能原子地获取值,以避免竞争条件,其他东西已将其设置为不同的值。
If you don't know the name of the module until runtime you'll have to do the translation between module name (My::Module) and file name (My/Module.pm) manually:
如果您在运行时之前不知道模块的名称,则必须手动执行模块名称(My :: Module)和文件名(My / Module.pm)之间的转换:
my $module = 'My::Module';
eval {
(my $file = $module) =~ s|::|/|g;
require $file . '.pm';
$module->import();
1;
} or do {
my $error = $@;
# ...
};
#2
16
How about using the core module Module::Load
如何使用核心模块Module :: Load
With your example:
用你的例子:
use Module::Load;
my $module = "My::module";
load $module;
"Module::Load - runtime require of both modules and files"
“Module :: Load - 运行时需要模块和文件”
"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: ...".
如果它失败了它会死于类似“无法在@INC中找到xxx(@INC包含:......”)。
#3
10
Well, there's always require
as in
好吧,总是要求如此
require 'My/Module.pm';
My::Module->import();
Note that you lose whatever effects you may have gotten from the import
being called at compile time instead of runtime.
请注意,在编译时调用导入而不是运行时,可能会丢失可能产生的任何影响。
Edit: The tradeoffs between this and the eval way are: eval lets you use the normal module syntax and gives you a more explicit error if the module name is invalid (as opposed to merely not found). OTOH, the eval way is (potentially) more subject to arbitrary code injection.
编辑:这与eval方式之间的权衡是:eval允许您使用普通模块语法,如果模块名称无效(而不是仅仅找不到),则会给出更明确的错误。 OTOH,eval方式(可能)更容易受到任意代码注入。
#4
4
No, it's not possible to without
eval
, as
require()
needs the bareword module name, as described at
perldoc -f require. However, it's not an evil use of eval, as it doesn't allow injection of arbitrary code (assuming you have control over the contents of the file you are
require
ing, of course).
不,没有eval是不可能的,因为require()需要裸字模块名称,如perldoc -f require所述。但是,它并不是eval的恶意用法,因为它不允许注入任意代码(假设您可以控制所需文件的内容,当然)。
EDIT: Code amended below, but I'm leaving the first version up for completeness.
编辑:下面修改了代码,但我要完成第一个版本。
I use
I used to use this little sugar module to do dynamic loads at runtime:
我使用我曾经使用这个小糖模块在运行时进行动态加载:
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our @EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports);
sub requireClass
{
my ($class) = @_;
eval "require $class" or do { die "Ack, can't load $class: $@" };
}
1;
PS. I'm staring at this definition (I wrote it quite a while ago) and I'm pondering adding this: $class->export_to_level(1, undef, @imports);
... it should work, but is not tested.
PS。我正在盯着这个定义(我很久以前写过)而且我正在考虑添加这个:$ class-> export_to_level(1,undef,@ import); ...它应该可以工作,但是没有经过测试。
EDIT: version 2 now, much nicer without an eval (thanks ysth): :)
编辑:现在版本2,没有评估更好(感谢ysth)::)
package MyApp::Util::RequireClass;
use strict;
use warnings;
use Exporter 'import'; # gives you Exporter's import() method directly
our @EXPORT_OK = qw(requireClass);
# Usage: requireClass(moduleName);
# does not do imports (wrong scope) -- you should do this after calling me: $class->import(@imports);
sub requireClass
{
my ($class) = @_;
(my $file = $class) =~ s|::|/|g;
$file .= '.pm';
require $file; # will die if there was an error
}
1;
#5
1
Class::MOP on CPAN has a load_class method for this: http://metacpan.org/pod/Class::MOP
CPAN上的Class :: MOP有一个load_class方法:http://metacpan.org/pod/Class :: Male
#6
0
i like doing things like..
我喜欢做像......
require Win32::Console::ANSI if ( $^O eq "MSWin32" );
需要Win32 :: Console :: ANSI if($ ^ O eq“MSWin32”);