使用自定义模块后,在分配给错误名称空间的必需文件中定义的子例程
Subroutines defined in required file assigned to wrong namespace after use of custom module
在我正在处理的脚本中,我有类似于以下内容的内容:
require "environment.pm"; # Various definitions, including subroutine get_coll()
use Custom::Module;
在 Custom::Module
文件中,我从
开始
package Custom::Module;
并以
结尾
1;
当我尝试调用 get_coll()
时出现错误:
( main::get_coll() ) being undefined.
如果我需要 Custom::Module
而不是使用或将调用更改为
Custom::Module::get_coll();
它工作正常。这让我相信 CustomModule
的 "use" 语句正在改变 "active" 命名空间,所以当 get_coll()
被处理时(因为它是在调用时处理的)它被分配给那个命名空间而不是 main。这似乎不是常规 perl 模块的问题,但从我浏览过的模块来看,我没有注意到任何不同之处会导致命名空间 "revert" 在模块加载后返回到 main .如果能更好地理解命名空间的使用或修复模块以防止出现此问题,我们将不胜感激。
旁注:"require" 模块对我来说不是什么大问题,但这对我来说是意想不到的行为,所以我主要只是想更好地理解为什么会发生这种情况。
您误认为 require
与 use
在定义名称空间子例程方面有任何不同。事实并非如此。而且你误认为 use
影响了当前的包。它没有。
# Custom/Module.pm
package Custom::Module;
# the namespace is now "Custom::Module"
sub foo { ... } # defines &Custom::Module::foo
sub bar { ... } # defines &Custom::Module::bar
1; # end of Custom/Module.pm
---
# mainScript.pl
# without an explicit 'package' statement, we are in namespace "main"
use Custom::Module; # parses Custom/Module.pm
# but when the 'use' statement is complete, we are still in namespace "main"
sub baz { ... } # defines &main::baz
$x = baz(); # calls &main::baz
$y = foo(); # calls &main::foo, error if main::foo not defined
$z = Custom::Module::bar(); # calls &Custom::Module::bar
...
注释描述了我们在每个文件的每个部分中所处的名称空间。如果我们说 require Custom::Module
而不是 use Custom::Module
,其中的 None 会有任何不同。
现在,当没有 main::bar()
时,一直输入 Custom::Module::bar()
可能会很麻烦,而且您将指的是哪个 bar
子例程也没有歧义。让 perl 将对 bar
的调用识别为引用 Custom::Module::bar
的关键是将子例程引用从 Custom::Module
复制到当前名称空间中。也就是说,使 main::bar()
引用与 Custom::Module::bar()
.
相同的子例程
执行此操作的规范方法是使用 Exporter
模块。执行此操作的低级方法(以及 Exporter
在幕后所做的事情)是操纵 perl 的符号 tables.
对于您的具体问题,您可以像这样使用 Exporter
:
# Custom/Module.pm
package Custom::Module;
use base 'Exporter'; # make Custom::Module inherit from Exporter
our @EXPORT = qw(foo bar);
sub foo { ... }
sub bar { ... }
...
1;
现在任何其他调用 use Custom::Module
的文件都会将函数 get_coll
导入到其命名空间中。这是在 Exporter
中通过操纵符号 table 在幕后完成的。具体来说,从包 main
调用 use Custom::Module
将得到 Exporter
来进行类似
的 typeglob 赋值
*main::foo = *Custom::Module::foo;
这将使您从 main::foo()
调用的函数调用在 Custom::Module::foo()
.
中定义的代码
我已尝试完全按照您的描述重新创建文件。这是我的三个源文件
你说
In a script I am working on, I have something similar to the following:
require "environment.pm"; # Various definitions, including subroutine get_coll()
use Custom::Module;
和
When I try to call get_coll() I get an error about it
虽然你没有说你在哪里调用get_coll
,我猜它在主脚本中,我认为这相当于这个脚本文件
my_script.pl
use strict;
use warnings;
use 5.010;
require 'environment.pm';
use Custom::Module;
say get_coll();
和这个模块文件
environment.pm
use strict;
use warnings;
use 5.010;
sub get_coll {
return 'coll';
}
1;
然后你说
In the Custom::Module
file, I start with
package Custom::Module;
and end with
1;
所以我写了这个模块文件。它没有任何内容,因为你没有描述任何内容
Custom/Module.pm
use strict;
use warnings;
use 5.010;
package Custom::Module;
1;
现在,当我 运行 my_script.pl
我得到
coll
没有警告或错误消息,这完全符合我的预期
我担心你说 environment.pm
包含 get_coll
,但你可以调用 Custom::Module::get_coll
。 Custom/Module.pm
也有 require 'environment.pm'
吗?
如果您能指出我误解了您的描述的地方,请指出,因为我目前无法复制您的问题,因此无法帮助您
否则,我建议您尝试使用这三个文件来创建 Short, Self-Contained, Correct Example 您的问题。这将极大地帮助我们为您找到解决方案
在我正在处理的脚本中,我有类似于以下内容的内容:
require "environment.pm"; # Various definitions, including subroutine get_coll()
use Custom::Module;
在 Custom::Module
文件中,我从
package Custom::Module;
并以
结尾1;
当我尝试调用 get_coll()
时出现错误:
( main::get_coll() ) being undefined.
如果我需要 Custom::Module
而不是使用或将调用更改为
Custom::Module::get_coll();
它工作正常。这让我相信 CustomModule
的 "use" 语句正在改变 "active" 命名空间,所以当 get_coll()
被处理时(因为它是在调用时处理的)它被分配给那个命名空间而不是 main。这似乎不是常规 perl 模块的问题,但从我浏览过的模块来看,我没有注意到任何不同之处会导致命名空间 "revert" 在模块加载后返回到 main .如果能更好地理解命名空间的使用或修复模块以防止出现此问题,我们将不胜感激。
旁注:"require" 模块对我来说不是什么大问题,但这对我来说是意想不到的行为,所以我主要只是想更好地理解为什么会发生这种情况。
您误认为 require
与 use
在定义名称空间子例程方面有任何不同。事实并非如此。而且你误认为 use
影响了当前的包。它没有。
# Custom/Module.pm
package Custom::Module;
# the namespace is now "Custom::Module"
sub foo { ... } # defines &Custom::Module::foo
sub bar { ... } # defines &Custom::Module::bar
1; # end of Custom/Module.pm
---
# mainScript.pl
# without an explicit 'package' statement, we are in namespace "main"
use Custom::Module; # parses Custom/Module.pm
# but when the 'use' statement is complete, we are still in namespace "main"
sub baz { ... } # defines &main::baz
$x = baz(); # calls &main::baz
$y = foo(); # calls &main::foo, error if main::foo not defined
$z = Custom::Module::bar(); # calls &Custom::Module::bar
...
注释描述了我们在每个文件的每个部分中所处的名称空间。如果我们说 require Custom::Module
而不是 use Custom::Module
,其中的 None 会有任何不同。
现在,当没有 main::bar()
时,一直输入 Custom::Module::bar()
可能会很麻烦,而且您将指的是哪个 bar
子例程也没有歧义。让 perl 将对 bar
的调用识别为引用 Custom::Module::bar
的关键是将子例程引用从 Custom::Module
复制到当前名称空间中。也就是说,使 main::bar()
引用与 Custom::Module::bar()
.
执行此操作的规范方法是使用 Exporter
模块。执行此操作的低级方法(以及 Exporter
在幕后所做的事情)是操纵 perl 的符号 tables.
对于您的具体问题,您可以像这样使用 Exporter
:
# Custom/Module.pm
package Custom::Module;
use base 'Exporter'; # make Custom::Module inherit from Exporter
our @EXPORT = qw(foo bar);
sub foo { ... }
sub bar { ... }
...
1;
现在任何其他调用 use Custom::Module
的文件都会将函数 get_coll
导入到其命名空间中。这是在 Exporter
中通过操纵符号 table 在幕后完成的。具体来说,从包 main
调用 use Custom::Module
将得到 Exporter
来进行类似
*main::foo = *Custom::Module::foo;
这将使您从 main::foo()
调用的函数调用在 Custom::Module::foo()
.
我已尝试完全按照您的描述重新创建文件。这是我的三个源文件
你说
In a script I am working on, I have something similar to the following:
require "environment.pm"; # Various definitions, including subroutine get_coll() use Custom::Module;
和
When I try to call get_coll() I get an error about it
虽然你没有说你在哪里调用get_coll
,我猜它在主脚本中,我认为这相当于这个脚本文件
my_script.pl
use strict;
use warnings;
use 5.010;
require 'environment.pm';
use Custom::Module;
say get_coll();
和这个模块文件
environment.pm
use strict;
use warnings;
use 5.010;
sub get_coll {
return 'coll';
}
1;
然后你说
In the
Custom::Module
file, I start withpackage Custom::Module;
and end with
1;
所以我写了这个模块文件。它没有任何内容,因为你没有描述任何内容
Custom/Module.pm
use strict;
use warnings;
use 5.010;
package Custom::Module;
1;
现在,当我 运行 my_script.pl
我得到
coll
没有警告或错误消息,这完全符合我的预期
我担心你说 environment.pm
包含 get_coll
,但你可以调用 Custom::Module::get_coll
。 Custom/Module.pm
也有 require 'environment.pm'
吗?
如果您能指出我误解了您的描述的地方,请指出,因为我目前无法复制您的问题,因此无法帮助您
否则,我建议您尝试使用这三个文件来创建 Short, Self-Contained, Correct Example 您的问题。这将极大地帮助我们为您找到解决方案