Perl Cygwin весело. Модуль загружен, но не найден программой

Хорошо, несколько правил:

  • Нет, я не могу установить Strawberry Perl в этой системе. Я должен использовать Cygwin.
  • Это Perl 5.8.7. Я не могу обновить его.
  • Это не моя система. Это система заказчика, и я не могу модифицировать ее по своему усмотрению.

Теперь мы избавились от этого...

Я установил Spreadsheet::Read, Spreadsheet::ParseExcel и Spreadsheet::XLSX в этой системе. Это установило небольшой Perl-скрипт под названием xlscat. Мы делали это раньше на блоке разработки и блоке UAT. Теперь это производственная коробка.

Я получаю следующую ошибку:

Parser for XLSX is not installed at /usr/bin/xlscat line 185

Я проследил это до Spreadsheet::Read. Соответствующий код:

my @parsers = (
    [ csv       => "Text::CSV_XS"               ],
    [ csv       => "Text::CSV_PP"               ], # Version 1.05 and up
    [ csv       => "Text::CSV"                  ], # Version 1.00 and up
    [ ods       => "Spreadsheet::ReadSXC"       ],
    [ sxc       => "Spreadsheet::ReadSXC"       ],
    [ xls       => "Spreadsheet::ParseExcel"    ],
    [ xlsx      => "Spreadsheet::XLSX"          ],
    [ prl       => "Spreadsheet::Perl"          ],

    # Helper modules
    [ ios       => "IO::Scalar"                 ],
    );
my %can = map { $_->[0] => 0 } @parsers;
for (@parsers) {
    my ($flag, $mod) = @$_;
    print STDERR qq(DEBUG: Flag = "$flag" Mod = "$mod"\n);
    $can{$flag} and next;
    eval "require $mod; \$can{\$flag} = '$mod'";
    }
print STDERR Dumper(\%can); #DEBUG:

Строки, которые начинаются со строки DEBUG:, принадлежат мне.

Дамп @parsers показывает, что все загружается корректно. Первая отладка правильно выводит значения $flag и $mod.

Проблема, похоже, связана с оператором eval. Из того, что я вижу, он запускает require для модуля, а затем устанавливает переменную $can{$flag} в $mod, если запрос выполнен успешно. Судя по всему, require Spreadsheet::XLSX не работает. Вот соответствующий вывод из моих операторов отладки:

DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
      'csv' => 'Text::CSV_XS',
      'sxc' => 0,
      'xlsx' => 0,
      'xls' => 'Spreadsheet::ParseExcel',
      'ios' => 'IO::Scalar',
      'prl' => 0,
      'ods' => 0
    };

Хммм... Может модуль не установлен?

$ perldoc -l Spreadsheet::XLSX
/usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm

Он появляется в perldoc. Давайте напишем быструю тестовую программу:

#! /usr/bin/env perl

use Spreadsheet::Read;
use Spreadsheet::XLSX;

print "It works\n";

И...

$ ./test.pl
DEBUG: Flag = "csv" Mod = "Text::CSV_XS"
DEBUG: Flag = "csv" Mod = "Text::CSV_PP"
DEBUG: Flag = "csv" Mod = "Text::CSV"
DEBUG: Flag = "ods" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "sxc" Mod = "Spreadsheet::ReadSXC"
DEBUG: Flag = "xls" Mod = "Spreadsheet::ParseExcel"
DEBUG: Flag = "xlsx" Mod = "Spreadsheet::XLSX"
DEBUG: Flag = "prl" Mod = "Spreadsheet::Perl"
DEBUG: Flag = "ios" Mod = "IO::Scalar"
$VAR1 = {
          'csv' => 'Text::CSV_XS',
          'sxc' => 0,
          'xlsx' => 0,
          'xls' => 'Spreadsheet::ParseExcel',
          'ios' => 'IO::Scalar',
          'prl' => 0,
          'ods' => 0
        };
It works

Я могу подобрать Spreadsheet::XLSX через use Spreadsheet::XLSX в моей тестовой программе, но require в Spreadsheet::Read, похоже, его не видит.

Почему?


Приложение

Что вы получите, если напечатаете Dumper(\%INC)? - Фридо 2 минуты назад

Я на самом деле сделал один лучше. Я добавил в цикл следующую строку:

require $mod if ($mod eq "Spreadsheet::XLSX"); #DEBUG

И это вызвало сообщение об ошибке:

Can't locate Spreadsheet::XLSX in @INC (@INC contains:
    /usr/lib/perl5/5.8/cygwin /usr/lib/perl5/5.8
    /usr/lib/perl5/site_perl/5.8/cygwin
    /usr/lib/perl5/site_perl/5.8
    /usr/lib/perl5/site_perl/5.8/cygwin
    /usr/lib/perl5/site_perl/5.8 
    /usr/lib/perl5/vendor_perl/5.8/cygwin
    /usr/lib/perl5/vendor_perl/5.8 
    /usr/lib/perl5/vendor_perl/5.8/cygwin
    /usr/lib/perl5/vendor_perl/5.8 .) at 
    /usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm line 57.
Compilation failed in require at ./test.pl line 3.
BEGIN failed--compilation aborted at ./test.pl line 3.

(ПРИМЕЧАНИЕ: я переформатировал выходные данные, чтобы они не превышали 1000 символов, и было легче увидеть путь @INC).

Модуль находится в /usr/lib/perl5/site_perl/5.8/Spreadsheet/XLSX.pm.

О, взгляните и на это:

$ pwd
/usr/lib/perl5/site_perl/5.8/Spreadsheet

$ ls -la
total 152
drwxr-xr-x+  4 phalder   Domain Users      0 Nov  1 21:51 .
drwxrwxrw-+ 11 twinborne Users             0 Nov  1 22:28 ..
drwxr-xr-x+  3 phalder   Domain Users      0 Nov  1 20:48 ParseExcel
-rwxr-xr-x   1 phalder   Domain Users 107773 Apr  6  2011 ParseExcel.pm
-rwxrwxrwx   1 phalder   Domain Users  29142 Nov  2 12:53 Read.pm
drwxr-xr-x+  2 phalder   Domain Users      0 Nov  1 21:51 XLSX
-rwxr-xr-x   1 phalder   Domain Users   8411 May 16  2010 XLSX.pm

$ ls -la XLSX
total 48
drwxr-xr-x+ 2 phalder Domain Users     0 Nov  1 21:51 .
drwxr-xr-x+ 4 phalder Domain Users     0 Nov  1 21:51 ..
-rwxr-xr-x  1 phalder Domain Users  5487 May 16  2010 Fmt2007.pm
-rwxr-xr-x  1 phalder Domain Users 37046 May 16  2010 Utility2007.pm

Разрешения вроде в порядке.


Еще одно дополнение:

Когда я сделал переустановку CPAN, я получил это:

Result: PASS
  /usr/bin/make test -- OK
Running make install
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ERROR: Can't create '/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
Do not have write permissions on     
'/usr/lib/perl5/site_perl/5.8/cygwin/auto/Spreadsheet/Read'
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 at -e line 1
Installing /usr/lib/perl5/site_perl/5.8/Spreadsheet/Read.pm
Installing /usr/share/man/man3/Spreadsheet.Read.3pm
make: *** [pure_site_install] Error 255
   /usr/bin/make install  -- NOT OK

Ой! Я не проверял разрешение дерева каталогов /usr/lib/perl5/site_perl/5.8/cygwin.

Сделал chmod -R a+rx * для всего каталога /usr/lib/perl5. Посмотрим, сработает ли снова.


person David W.    schedule 02.11.2011    source источник
comment
Что вы получите, если print Dumper( \%INC ) ?   -  person friedo    schedule 02.11.2011
comment
@friedo - см. мое дополнение внизу поста. Вы увидите, что @INC в порядке, как и права доступа к файлам.   -  person David W.    schedule 02.11.2011
comment
require $mod делает не то, что вы думаете. См. perldoc -f require. Вам нужно eval "require $mod"   -  person Sinan Ünür    schedule 02.11.2011
comment
Что находится в $@ после оператора eval "require $mod ..."?   -  person mob    schedule 02.11.2011
comment
@SinanÜnür - Что значит не делает то, что, по вашему мнению, делает? Где мне нужно eval "$require $mod? Spreadsheet::Read уже выполняет оценку. Я сделал это без eval, поэтому я вижу ошибку.   -  person David W.    schedule 02.11.2011
comment
@mod - я решил снова переустановить модули электронных таблиц через cpan и посмотреть, исчезнет ли проблема. Если у меня возникнут те же проблемы, я проверю значение как @INC, так и %INC.   -  person David W.    schedule 02.11.2011
comment
Если $mod содержит строку Spreadsheet::XLSX, то require $mod ищет файл Spreadsheet::XLSX, а не Spreadsheet/XLSX.pm. Вот почему вам нужно eval "require $mod".   -  person Sinan Ünür    schedule 02.11.2011
comment
Ах. Я понимаю. Ты прав. Я не могу использовать переменную или кавычки. Ну, по крайней мере, мы видим, чему равно @INC. Я делаю переустановку и смотрю, что происходит. Если это не сработает, я изменю этот оператор, чтобы удалить $mod и сделать прямое require Spreadsheet::XLSX.   -  person David W.    schedule 02.11.2011
comment
Еще одно дополнение: кажется, я нашел проблему...   -  person David W.    schedule 02.11.2011
comment
Я нашел проблему. См. ответ Найдена проблема   -  person David W.    schedule 02.11.2011


Ответы (1)


Нашел проблему

Я взял немного другой такт. Я изменил Spreadsheet::Read, чтобы распечатать $@ после eval. Таким образом, я мог видеть, какую ошибку он получает. Вот результаты:

$ ./test.pl
DEBUG: ""DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in @INC
(@INC contains:
    /usr/lib/perl5/5.8/cygwin
    /usr/lib/perl5/5.8
    /usr/lib/perl5/site_perl/5.8/cygwin
    /usr/lib/perl5/site_perl/5.8
    /usr/lib/perl5/site_perl/5.8/cygwin
    /usr/lib/perl5/site_perl/5.8
    /usr/lib/perl5/vendor_perl/5.8/cygwin
    /usr/lib/perl5/vendor_perl/5.8
    /usr/lib/perl5/vendor_perl/5.8/cygwin
    /usr/lib/perl5/vendor_perl/5.8 .) at (eval 8) line 1.
"DEBUG: "Can't locate Spreadsheet/ReadSXC.pm in @INC
(@INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 9) line 1.
"DEBUG: ""DEBUG: "Can't locate Compress/Raw/Zlib.pm in @INC
(@INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 15) line 1.
"DEBUG: "Can't locate Spreadsheet/Perl.pm in @INC
(@INC contains: /usr/lib/perl5/5.8/cygwin [...]) at (eval 18) line 1.

Ты это видел? Проблема не Spreadsheet::XLSX, а Compress::Raw::Zlib. Я установил все разрешения для /usr/lib/perl на 777, а затем установил Compress::Raw::Zlib и Spreadsheet::ReadSXC.

Это, должно быть, было проблемой, когда эти модули были первоначально установлены. Не я устанавливал cpan, а помогал человеку по телефону, поэтому у меня не было возможности увидеть эти ошибки, если они появлялись. CPAN имеет тенденцию быть очень, очень шумным, и я научился ловить случайные сообщения об ошибках, когда CPAN работает.

Возможно, проблема заключалась в том, что /usr/lib/perl5/site_perl/5.8/cygwin у вас все время не было правильных разрешений.

Теперь программа работает.

Спасибо за всю твою помощь. Каким-то образом это привело меня на правильный путь.

person David W.    schedule 02.11.2011