2015-05-05 2 views
0

Я пытаюсь создать ряд связанных классов в одном пространстве имен, но классы не могут найти друг друга.Perl - использовать связанные модули в иерархии пакетов

Я работаю в пространстве имён Crypt::HSXKPasswd. Мои файлы .pm находятся в правильных путях файлов в папке ./lib (Crypt::HSXKPasswd определяется в ./lib/Crypt/HSXKPasswd.pm и т. Д.).

Внутри конструктора моего основного модуля (Crypt::HSXKPasswd->new) Я пытаюсь создать объект типа Crypt::HSXKPasswd::Dictionary::Default.

Мой тестовый файл находится в ., и имеет следующее содержание:

#!/usr/bin/perl 

use strict; 
use warnings; 
use lib './lib'; 
use Crypt::HSXKPasswd; 

my $hsxkpasswd = Crypt::HSXKPasswd->new(); 

Он не выполняет со следующей ошибкой:

Can't locate Crypt::HSXKPasswd::Dictionary::Default in @INC (@INC contains: ./lib /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.2/darwin-thread-multi-2level /Library/Perl/Updates/5.18.2 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at lib/Crypt/HSXKPasswd.pm line 482. 

Обратите внимание, что @INC содержит ./lib. Следующая команда главы показывает, что файл .pm для модуля находится в правильном пути под ./lib, и что он делает определить правильный пакет:

$ head -1 ./lib/Crypt/HSXKPasswd/Dictionary/Default.pm 
package Crypt::HSXKPasswd::Dictionary::Default; 
$ 

Если файл .pm существует, определяет модуль, и расположена в правильном пути относительно папки в @INC, почему Perl не видит его?

+1

в вашем файле 'Crypt :: HSXKPasswd' вам нужно использовать Crypt :: HSXKPasswd :: Dictionary :: Default;' – KeepCalmAndCarryOn

+0

'Crypt :: HSXKPasswd :: Dictionary :: Default' - имя пакета не было преобразовано для имени файла. Не могли бы вы опубликовать пару строк вокруг оператора использования (до изменения, которое исправило его)? Спасибо. – Dallaylaen

+0

@ Dallaylaen - У меня больше нет сломанного кода, но это директива require, а не директива use, и если память служит, она использует строку, а не голые слова, и вполне может объяснить всю проблему. –

ответ

1

Примечание Crypt::HSXKPasswd::Dictionary::Default в сообщении об ошибке - это не превращали в Crypt/HSXKPasswd/Dictionary/Default.pm, поэтому Perl пытался загрузить пакет буквально, так и не удалось.

Это может произойти в случае использования, как следует:

my $foo = "Foo::Bar"; 
require $foo; # tries lo load literal Foo::Bar 

Это можно преодолеть с помощью Module::Load, которые автоопределение ли вы собираетесь загрузить модуль или файл.

use Module::Load; 

# later 
my $foo = "Foo::Bar"; 
load $foo; 

Или можно использовать строку Eval:

my $foo = "Foo::Bar"; 
eval "require $foo" or die [email protected]; 

Но обратите внимание, что evil ИНГ струн могут быть опасны, поэтому проверьте переменную дважды два раза в этом случае.

1

Скорее всего, ваш текущий рабочий каталог не там, где вы думаете, что он находится во время загрузки модуля. Что-то в одном из ваших модулей может изменить текущий рабочий каталог. Например, я могу воспроизвести проблему, имеющим модуль, который выглядит следующим образом:

package Crypt::HSXKPasswd; 

BEGIN { chdir("/"); } 

use strict; 
use warnings; 
use Crypt::HSXKPasswd::Dictionary::Default; 

1; 

Ваша проблема скорее всего, не является ли это просто, но вы, вероятно, есть модуль где-то в цепочке делать что-то подобное, будь то через что-то как прямо так, как утверждение BEGIN, или менее очевидным, так как путем изменения каталога перед оператором require. Учитывая, что ваш модуль не работает в строке 482, вероятно, это не оператор use, загружающий модуль (обычно они перечислены в верхней части пакета), поэтому я наклоняюсь к chdir(), инициированному где-то перед require.

0

По причинам, которые я не понимаю, изменяющиеся от использования require в конструкторе только тогда, когда Crypt::HSXKPasswd::Dictionary::Default было необходимо (необходимо только для некоторых путей через конструктор), просто импортировать его с use заявления в верхней части файла, исправлена ​​проблема.

Я думаю, что мораль этой истории, вероятно, не должна слишком быстро оптимизироваться, а не пытаться быть слишком умной для вашего же блага!

+1

См. [Мой ответ] (http://stackoverflow.com/a/30043596/1735796). Причина, которая работает для вас, заключается в том, что 'require' происходит во время выполнения, тогда как' use' происходит во время компиляции. Поскольку ваш оператор 'use lib' ссылается на относительный путь, если ваш рабочий каталог изменяется (что относится к тому, что путь относительный), тогда скрипт больше не сможет загружать модули из этого относительного пути во время выполнения. – hrunting

Смежные вопросы