Perl - проблемы с пакетами / модулями - PullRequest
7 голосов
/ 05 июня 2010

Из всего, что я читал об использовании модулей Perl, основное использование:

  • Файл модуля с расширением .pm, который включает оператор package <name>, где <name> - имя файла модуля без расширения.
  • Файл кода, в котором используется модуль, содержит оператор use <name>;.

Приложение, которое я кодирую, имеет один сценарий основного кода, который использует около 5 модулей. Я забыл включить оператор package <name> в модули, но мой код по-прежнему прекрасно работал с оператором use <name>. Я начал получать Undefined subroutine ошибок с одним из модулей, поэтому я добавил инструкцию package для каждого из модулей. Теперь остальные модули перестали работать . Что дает?

* ** 1019 1020 * Пример: * ** 1022 тысячу двадцать одна *

mainapp.pl

#!/usr/bin/perl
use UtyDate;
my $rowDate = CurrentDate("YYYYMMDD");

UtyDate.pm

#!/usr/bin/perl
package UtyDate;
sub CurrentDate
{
    #logic
}
return 1;

Когда я запускаю приведенный выше код, я получаю ошибку Undefined subroutine &main::CurrentDate called at.... Однако, если я удаляю строку package UtyDate; из UtyDate.pm, я не получаю ошибки. Такая ситуация существует для нескольких, но не для всех моих модулей.

Очевидно, что я не показываю намного больше кода, но я запутался, как любой код, который я не показываю, может повлиять на конструкции пакета / использования, которые я здесь показал.

Ответы [ 4 ]

10 голосов
/ 05 июня 2010

Когда вы используете модуль, код в модуле запускается во время компиляции. Затем вызывается импорт по имени пакета для модуля. Итак, use Foo; совпадает с BEGIN { require Foo; Foo->import; }

Ваш код работал без объявлений package, поскольку весь код был выполнен в пакете main, который используется основным кодом приложения.

Когда вы добавили объявления package, он перестал работать, поскольку определенные вами подпрограммы больше не определяются в main, а в UtyDate.

Вы можете получить доступ к подпрограммам, используя полное имя UtyDate::CurrentDate(); или импортировав подпрограммы в текущее пространство имен при use модуле.

UtyDate.pm

package UtyDate;
use strict;
use warnings; 

use Exporter 'import';

# Export these symbols by default.  Should be empty!    
our @EXPORT = ();

# List of symbols to export.  Put whatever you want available here.
our @EXPORT_OK = qw( CurrentDate  AnotherSub ThisOneToo );

sub CurrentDate {
    return 'blah';
}

sub AnotherSub { return 'foo'; }

Основная программа:

#!/usr/bin/perl
use strict;
use warnings; 

use UtyDate 'CurrentDate';

# CurrentDate is imported and usable.    
print CurrentDate(), " CurrentDate worked\n";

# AnotherSub is not
eval {  AnotherSub() } or print "AnotherSub didn't work: $@\n";

# But you can still access it by its fully qualified name
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n";

См. Экспортер документов для получения дополнительной информации.

3 голосов
/ 05 июня 2010

Вам не хватает кода заголовка perl экспортера. Вам нужно будет добавить что-то вроде следующего в верхнюю часть вашего файла pm ниже инструкции package:

package UtyDate;
BEGIN {
  use Exporter ();
  use vars qw($VERSION @ISA @EXPORT);
  $VERSION = "1.0.0";
  @ISA = qw(Exporter);
  @EXPORT = qw( &CurrentDate );
}

См. Ссылку: http://perldoc.perl.org/Exporter.html#DESCRIPTION

1 голос
/ 05 июня 2010

В качестве альтернативы предложению Грея вы можете сделать это:

use UtyDate;
UtyDate::CurrentDate(...);
0 голосов
/ 05 июня 2010

Помимо использования экспортера, как указывает Грей, вы могли (некрасиво, но работает) также вызывать функции с именем модуля.

Вы функционировали / процедуры не работают, так как теперь они находятся в другом пространстве имен (определенном именем модуля)

use UtyDate;

UtyDate::CurrentDate(  )
...