2010-09-07 57 views
1

我遇到了使用配置文件中定義的常量的問題。 這是我的包:導入require'd文件,就好像它是一個使用語句

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. 

我不能使用 '使用'而不是'require',因爲這需要將配置文件命名爲.pm,並且在我們網絡上的很多服務器上都將其命名爲.pl。 如何在不重命名文件的情況下使用包?

回答

7

'use'和'require'有兩個區別。其中一個會影響你目前的問題,另一個則不會。不幸的是,你正在解決一個沒有效果的解決方案。

的區別是:

1/'使用' 調用導入()函數, '需要' 不。

2'use'發生在編譯時,'require'發生在運行時。

您正在解決'require'通過顯式調用它不會調用import()的事實。這不會影響你的模塊不導出任何符號,也沒有import()子程序。

你沒有解決'use'語句在運行時被執行的事實。問題是「使用常量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作爲一個真正的模塊。你暗示你知道這一點,但環境問題阻止你採取這種方法。我強烈建議您嘗試解決這些問題並正確處理問題。

2

這不可能是正確的 - 程序包APIconfig中沒有子程序import。一旦使用完整的包路徑訪問符號名稱,無論如何您都不需要導出/導入。

解決的辦法是在編譯時運行require,在use constant之前。此作品:

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

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

如果它是一個配置文件,不要使它成爲代碼。關於這一點,我掌握了一整章掌握Perl,並且CPAN上有許多模塊可以幫助您處理幾乎所有的配置格式。

如果是代碼,爲什麼不把它做成模塊,以便您可以使用use。模塊在另一個程序中更容易控制和操作。

最簡單的解決方案就是那些你不會在潮水中游泳的地方。 :)

除此之外,use是一樣的:

BEGIN { 
     require Module; 
     Module->import; 
     } 

你只需要對文件名,它定義了命名空間(只要該文件中的代碼看起來像一個模塊),同樣的事情:

BEGIN { 
     require "file.pl"; # defines SomeNamespace 
     SomeNamespace->import; 
     } 
相關問題