【问题标题】:Perl Cygwin fun. Module is loaded, but not being found by the programPerl Cygwin 很有趣。模块已加载,但程序未找到
【发布时间】:2011-11-02 16:48:32
【问题描述】:

好的一些规则:

  • 不,我不能在这个系统上安装 Strawberry Perl。我必须使用 Cygwin。
  • 这是 Perl 5.8.7。我无法更新它。
  • 这不是我的系统。这是客户的系统,我无法随心所欲地对其进行修改。

现在,我们已经解决了这个问题......

我在这个系统上安装了Spreadsheet::ReadSpreadsheet::ParseExcelSpreadsheet::XLSX。这安装了一个名为xlscat 的小Perl 脚本。我们以前在开发盒和 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

我可以在我的测试程序中通过use Spreadsheet::XLSX 获取Spreadsheet::XLSX,但Spreadsheet::Read 中的require 似乎看不到它。

为什么?


附录

如果你打印 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目录树的权限。

在整个/usr/lib/perl5 目录上做了一个chmod -R a+rx *。我们会看看它是否会再次起作用。

【问题讨论】:

  • print Dumper( \%INC ) 会得到什么?
  • @friedo - 请参阅帖子底部的我的附录。您会看到@INC 很好,文件权限也很好。
  • require $mod 并没有按照你的想法去做。见perldoc -f require。你需要eval "require $mod"
  • $@eval "require $mod ..." 语句之后的内容是什么?
  • 如果$mod 包含字符串Spreadsheet::XLSX,则require $mod 会查找文件Spreadsheet::XLSX,而不是Spreadsheet/XLSX.pm。这就是为什么你需要eval "require $mod"

标签: perl cygwin perl-module


【解决方案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::ZlibSpreadsheet::ReadSXC

这一定是最初安装这些模块时出现的问题。我不是进行 cpan 安装的人,而是通过电话帮助这个人,所以如果它们弹出,我没有机会看到这些错误。 CPAN 往往非常非常嘈杂,我已经学会了在 CPAN 运行时捕捉随机错误消息。

问题可能是/usr/lib/perl5/site_perl/5.8/cygwin一直没有正确的权限。

程序现在可以运行了。

感谢您的所有帮助。不知何故,它引导我走上了正确的道路。

【讨论】:

    猜你喜欢
    • 2012-03-05
    • 2012-04-30
    • 1970-01-01
    • 2020-05-01
    • 2020-07-24
    • 2015-09-23
    • 2020-12-25
    • 2016-03-27
    • 2016-01-08
    相关资源
    最近更新 更多