2

我刚刚找到了一个我们正在使用的脚本,其中有一个子说明my %INC,其中存储了一些关于激励的值,因此%INC. 这似乎从来都不是问题,或者没有人注意到。对我来说,它产生了 20 个重新定义警告屏幕,因为%INC.perl 包含所有文件名done、required 或used,非常大,而现在是('stuff' => 123).

我真的必须去重命名 sub 中对 this 的每一个引用,还是有另一种方法可以让 Perl 原谅这个......?


这是输出的一部分:

print Dumper \%INC; # I added this line
my %INC;             
print Dumper \%INC; # I added this line
exit;               # I added this line

输出:

          [...]
          'SqlConnect.pm' => 'lib1/SqlConnect.pm',
          'Lib/RateRequest.pm' => 'Lib/RateRequest.pm'
        };
$VAR1 = {};
[Fri Jun 29 16:09:13 2012] live_batch_test.pl: Subroutine export_fail redefined at /usr/lib/perl5/5.14.2/Carp.pm line 43.
[Fri Jun 29 16:09:13 2012] live_batch_test.pl: Subroutine _cgc redefined at /usr/lib/perl5/5.14.2/Carp.pm line 45.
[Fri Jun 29 16:09:13 2012] live_batch_test.pl: Subroutine longmess redefined at /usr/lib/perl5/5.14.2/Carp.pm line 51.
[Fri Jun 29 16:09:13 2012] live_batch_test.pl: Subroutine shortmess redefined at /usr/lib/perl5/5.14.2/Carp.pm line 71.
[...] (Snipped like 20 screens of redefine warnings)

警告仅显示我是否创建了我的一个类的对象(它恰好包含SOAP::WSDL所以它有很多东西)。我不确定为什么这些是重新定义警告。如果%INC是空的,它怎么知道东西正在被重新定义?


更新:

看来您实际上可以创建一个词法my %INC.

use strict; use warnings; use Data::Dumper;
print Dumper \%INC;
{
  my %INC = ('asdf' => 'asdf');
  print Dumper \%INC;
}
print Dumper \%INC;

产生(剪断):

          'feature.pm' => 'C:/Perl/lib/feature.pm'
        };
$VAR1 = {
          'asdf' => 'asdf'
        };
$VAR1 = {
          'warnings/register.pm' => 'C:/Perl/lib/warnings/register.pm',

在我的情况下的问题似乎不是my %INC,而是%INC = &sub_that_has_my_percent_INC_and_returns_it()我实际上必须在脚本中require。现在,反过来,也有use vars qw(%INC)。更换它......好吧,我不确定它会破坏什么。

4

6 回答 6

4

全局变量%INC(或%main::INC%::INC)是与词法范围完全不同的变量%INC,由 . 创建my。您可以安全地my %INC在您的子程序中使用。

于 2012-06-29T14:33:39.200 回答
2

定义词法范围my %INC是可能的,但是这个变量绝对没有特殊含义。%INCPerl在使用模块系统时只考虑全局。

你的问题在别处

举个例子来娱乐你,给定:

下午

package Aaa;
warn "Aaa loaded!";

1;

公司

use strict;
use warnings;
use Data::Dumper;

use Aaa;
require Aaa;
warn 1, Dumper \%INC;
{
    my %INC;
    use Aaa;
    require Aaa;
    warn 2, Dumper \%INC;
}
warn 3, Dumper \%INC;
my %INC;
use Aaa;
require Aaa;

sub again {
    my %INC;
    require Aaa;
    warn 4, Dumper \%INC;
}

again();
warn 5, Dumper \%INC;

您只会%INC在 1 和 3 中看到全局,而不会对词法进行任何更改,并且Aaa.pm仍将仅加载一次。

于 2012-06-29T15:30:34.617 回答
1

perldoc vars表示vars编译指示已被our关键字取代。

遵循文档的建议似乎对我有用:

package Incentives;

use strict;
use warnings;
use Data::Dump 'dump';

our %INC = ( abc => 123 );

dump \%INC;                   # ( abc => 123 ),
                              # different under use vars '%INC';

use List::Util;               # Loads just fine

package Test;

use Data::Dump 'dump';

dump \%Incentives::INC;       # ( abc => 123 )
dump \%main::INC;             # reference to global %INC

1;
于 2012-06-29T17:02:13.473 回答
1

如果你触摸全局包变量%INC,你会遇到问题,但是你可以创建所有你想要的命名词法%INC,这不会是一个问题。

$ perl -e'require CGI; my %INC; require CGI;'

$ perl -e'require CGI; local %INC; require CGI;'
Subroutine export_fail redefined at .../Carp.pm line 64.
Subroutine _cgc redefined at .../Carp.pm line 66.
Subroutine longmess redefined at .../Carp.pm line 72.
Subroutine shortmess redefined at .../Carp.pm line 92.
Subroutine croak redefined at .../Carp.pm line 100.
Subroutine confess redefined at .../Carp.pm line 101.
Subroutine carp redefined at .../Carp.pm line 102.
Subroutine cluck redefined at .../Carp.pm line 103.
Constant subroutine Carp::CALLER_OVERRIDE_CHECK_OK redefined at .../Carp.pm line 108.
Subroutine caller_info redefined at .../Carp.pm line 114.
Subroutine format_arg redefined at .../Carp.pm line 181.
Subroutine get_status redefined at .../Carp.pm line 213.
Subroutine get_subname redefined at .../Carp.pm line 222.
Subroutine long_error_loc redefined at .../Carp.pm line 240.
Subroutine longmess_heavy redefined at .../Carp.pm line 268.
Subroutine ret_backtrace redefined at .../Carp.pm line 276.
Subroutine ret_summary redefined at .../Carp.pm line 309.
Subroutine short_error_loc redefined at .../Carp.pm line 324.
Subroutine shortmess_heavy redefined at .../Carp.pm line 348.
Subroutine str_len_trim redefined at .../Carp.pm line 361.
Subroutine trusts redefined at .../Carp.pm line 376.
Subroutine trusts_directly redefined at .../Carp.pm line 396.
Constant subroutine CGI::XHTML_DTD redefined at .../constant.pm line 151.
Subroutine _ops_to_nums redefined at .../overloading.pm line 10.
Subroutine import redefined at .../overloading.pm line 19.
Subroutine unimport redefined at .../overloading.pm line 37.

你说的不靠谱。您必须在%INC某处更改全局而不是词法。

于 2012-06-29T19:42:04.183 回答
0

我想我找到了实际的问题和处理它的方法。

我没有创建两个文件。

file1.pl有一些潜艇。这些潜艇之一做这样的事情:

sub foo {
  my %INC = (foo => 'bar'); # lexical variable, does not mess with global %INC
  return %INC;
}

file2.pl看起来像这样:

use vars qw(%INC);     # oops! global variable
require 'file1.pl';

sub bar1 {
  if (!$INC{'foo'}) {
    %INC = &foo();     # this is breaking stuff
  }
  my $hashref = {
    'inc' => \%INC,
  }
  return $hashref;
}

sub bar2 {
  if (!$INC{'foo2'}) {
    %INC = &foo();
  }
}
# and so on

我在file3.pl其中创建,我有:

use MyModule;
require 'file2.pl';

my $data = &bar1();
my $obj = MyModule->new();
$obj->doStuff();

现在,当我调用doStuff()它时,它会为全局中的每个项目打印一个重新定义警告%INC(由于 file2,现在它是空的)。

我搜索了代码库%INC,发现只有 file1 和 file2 使用它。所以我所做的就是将 file2 更改为:

use vars qw();
require 'file1.pl';

my %INC;     # now lexical, but still the same for all subs in this file
sub bar1 {
  if (!$INC{'foo'}) {
    %INC = &foo();     # this is not breaking stuff any more
  }
  my $hashref = {
    'inc' => \%INC,
  }
  return $hashref;
}

sub bar2 {
  if (!$INC{'foo2'}) {
    %INC = &foo();
  }
}
# and so on
于 2012-06-29T16:58:47.210 回答
0

尝试

no warnings 'redefine';

不过,在那个子例程中,这可能会在未来产生一些有趣的副作用

于 2012-06-29T14:25:24.010 回答