Perl是否有像python' s import as
?
如果模块没有指定一个软件包,那么这个hacky little解决方案可以起作用:
# mod1.pm
sub routine{ return "I'm from mod1\n"; }
# mod2.pm
sub routine{ return "I'm from mod2\n"; }
#!/usr/bin/perl
# similar to 'import mod1 as foo'
package foo;
require 'mod1.pm';
# similar to 'import mod2 as bar'
package bar;
require 'mod2.pm';
# now do some script stuff
package main;
print foo::routine();
print bar::routine();
如果模块带有自己的命名空间,那么这不起作用:
# ABC.pm
package ABC;
sub routine{ return "I'm from ABC\n"; }
# DEF.pm
package DEF;
sub routine{ return "I'm from DEF\n"; }
#!/usr/bin/perl
package foo;
require 'ABC.pm';
package bar;
require 'DEF.pm';
package main;
print foo::routine();
print bar::routine();
# These calls produce undefined subroutine errors.
是否可以导入文件,并将其内容强制插入特定的命名空间?
答案 0 :(得分:1)
您的模块实际上并未导出任何内容。
ABC.pm
:
package ABC;
use Exporter qw( import );
our @EXPORT = qw( routine );
sub routine { return __PACKAGE__ }
DEF.pm
:
package DEF;
use Exporter qw( import );
our @EXPORT_OK = qw( routine );
sub routine { return __PACKAGE__ }
script
:
package foo;
use ABC qw( routine );
package bar;
use DEF qw( routine );
package main;
print foo::routine(), "\n"; # ABC
print bar::routine(), "\n"; # DEF
您还可以使用以下内容:
use ABC qw( );
use DEF qw( );
BEGIN {
*foo_routine = \&ABC::routine; # Could use foo::routine if you wanted.
*bar_routine = \&DEF::routine;
}
print foo_routine(), "\n"; # ABC
print bar_routine(), "\n"; # DEF
use Module ()
和use Module qw()
会阻止调用模块import
。这里的模块没有定义任何默认导出,但我喜欢明确我导入的内容。
答案 1 :(得分:1)
从描述中我假设你既不控制ABC
也不控制foo
。
因为这两个中的任何一个都没有import
潜艇,所有潜艇都生活在各自的太空船中。因此,如果您加载foo
,则还会加载ABC
并且代码将可用于Perl。但ABC
中的子资源只能使用其完全限定名ABC::routine
来访问。
实际上,这与LWP :: UserAgent require
的HTTP :: Request时相同。现在,您可以在代码中使用HTTP :: Request而不使用use HTTP::Request
。你只把use LWP::UserAgent
放在那里,因为它加载了另一个,它现在可用。
当然那些不会出口的东西,所以它有点不同,但这基本上是在这里发生的。
但是,如果没有至少foo.pm
的控制权,则无法对此进行反击。您无法覆盖package
语句或声明程序的某些部分package
1}}没有做任何事情。
为了更进一步,您可能已经习惯了遗留代码,其中有.pl
个文件需要其他.pl
个文件且没有包。现在一个包成为一个问题,因为如果通常没有,并且没有Exporter
正在进行,那么东西就会变得很奇怪。
我经常需要在包中包含许多全局变量的遗留代码,以使它们远离我的main
命名空间。
package DoNotPutGlobalsInMyMain { require 'legacy.pl' };
但如果在package
内有另一个legacy.pl
的明确定义,这将会中断。所以我的上述说法仍然有效。您需要控制该代码来修复它,或者知道哪个包真正包含您要调用的子代码。
然后您可以自己打包use
或require
。只要foo.pm
已经加载它,就不会再次加载它(因为Perl在%INC
中记录了它已加载它)。但如果上游他们将其从foo.pm
中删除,它仍然可用。您的维护程序员也了解您的依赖项。
答案 2 :(得分:0)
如果您要加载DEF.pm
并将其作为bar
访问,可以通过typeglob执行此操作:
http://perldoc.perl.org/perldata.html#Typeglobs-and-Filehandles
http://perldoc.perl.org/perlmod.html#Symbol-Tables
#!/usr/bin/env perl
use strict;
use warnings;
package DEF;
sub routine {
print "Routine called\n";
}
package main;
local *foo::routine = *DEF::routine;
foo::routine();
这适用于包中的单个子更改符号表。
但我真的质疑为什么你需要这样做?你有两个冲突命名空间或什么?这是让代码更乱,而不是更干净的好方法,所以我一般不会建议它是一个好主意。
否则 - 您可以使用代码参考:
my $ref_to_routine = \&DEF::routine;
$ref_to_routine->();
&$ref_to_routine();