1

我在使用配置文件中定义的常量时遇到问题。这是我的包裹:

package myPackage;
require "APIconfig.pl";
APIconfig::import(APIconfig);

use constant SERVICE_URL => APIconfig::SERVICE_URL();

配置如下所示:

package APIconfig;
use constant SERVICE_URL => 'http://api.example.org/blah';
1;

运行此代码时,我收到以下错误:

Undefined subroutine &APIconfig::SERVICE_URL called at API.pl line 4.

我不能使用“use”而不是“require”,因为这需要配置文件被命名为 .pm,并且在我们网络上的许多服务器上它被称为 .pl。如何在不重命名文件的情况下使用包?

4

3 回答 3

7

“使用”和“要求”之间有两个区别。其中一个会影响您当前的问题,另一个不会。不幸的是,您正在解决一个没有效果的问题。

区别在于:

1/ 'use' 调用 import() 函数,'require' 没有。

2/ 'use' 发生在编译时,'require' 发生在运行时。

您正在解决“require”不会通过显式调用来调用 import() 的事实。这没有任何效果,因为您的模块不导出任何符号并且没有 import() 子例程。

您没有解决“使用”语句在运行时执行的事实。问题是“使用常量 SERVICE_URL => APIconfig::SERVICE_URL();” 在编译时执行并且你的'require'还没有运行,所以myPackage对APIconfig一无所知。

(讨厌的,hacky)解决方案是将“require”语句放入 BEGIN 块中 - 强制它在编译时执行。您还需要删除对 import() 的调用,因为这会导致运行时错误(由于缺少子例程)。

我用来解决这个问题的测试文件如下:

$ cat APIconfig.pl 
package APIconfig;
use constant SERVICE_URL => 'http://api.example.org/blah';
1;

$ cat api.pl 
#!/usr/bin/perl

package myPackage;
BEGIN {
  require "APIconfig.pl";
}
# APIconfig::import(APIconfig);

use constant SERVICE_URL => APIconfig::SERVICE_URL();

print SERVICE_URL, "\n";
$ ./api.pl 
http://api.example.org/blah

真正的解决方案是将 APIconfig 重写为真正的模块。你暗示你知道这一点,但环境问题阻止你采取这种方法。我强烈建议尝试解决这些问题并正确地做事。

于 2010-09-07T11:37:16.087 回答
2

这不可能是正确的 - importpackage中没有子例程APIconfig。一旦您使用完整的包路径访问符号名称,您就不需要导出/导入。

解决方案是require在编译时运行,在use constant. 这有效:

package myPackage;
BEGIN {
    require "APIconfig.pl";
}

use constant SERVICE_URL => APIconfig::SERVICE_URL();
于 2010-09-07T11:29:15.890 回答
1

如果它是一个配置文件,不要让它成为代码。我在Mastering Perl中有一整章介绍了这一点,并且 CPAN 上有许多模块可以帮助您处理几乎任何配置格式。

如果是代码,为什么不把它做成一个模块,这样你就可以使用use了。模块在另一个程序中更容易控制和操作。

最简单的解决方案是您不逆潮游泳的解决方案。:)

除此之外,用法与以下内容相同:

 BEGIN {
      require Module;
      Module->import;
      }

你只需对文件名和它定义的命名空间做同样的事情(只要文件中的代码看起来像一个模块):

 BEGIN {
      require "file.pl";  # defines SomeNamespace
      SomeNamespace->import;
      }
于 2010-09-07T20:32:11.400 回答