考虑以下简单模块MyCode.pm。它包含一个函数my_function
触摸文件然后重命名它。
#!/usr/bin/perl
package MyCode;
use strict;
use warnings;
use IO::File;
use File::Copy;
sub my_function {
# touch /tmp/a
my $fh = IO::File->new();
$fh->open(">/tmp/a") || die "open failed ($!)";
$fh->close() || die "close failed ($!)";
unlink("/tmp/aa"); # ignore errors; we want file removed
move("/tmp/a", "/tmp/aa") || die "move failed ($!)";
}
1;
现在考虑以下测试程序。它会成功覆盖IO::File::open
,IO::File::close
,但不会覆盖File::Copy::move
。为什么呢?
#!/usr/bin/perl -l
use strict;
use warnings;
use IO::File;
use File::Copy;
use MyCode;
{
no warnings 'redefine';
local *IO::File::open = sub {
eval {
$! = 44; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *IO::File::close = sub {
eval {
$! = 33; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
{
no warnings 'redefine';
local *File::Copy::move = sub {
eval {
$! = 22; # random value for illustration purposes
die;
};
};
eval {
MyCode::my_function()
};
print $@ if $@;
}
下面的程序输出。 move
覆盖没有输出,这意味着它没有启动。为什么?我也想知道为什么我会收到警告。
Name "IO::File::close" used only once: possible typo at ./test.pl line 28.
open failed (Channel number out of range) at MyCode.pm line 14.
close failed (Numerical argument out of domain) at MyCode.pm line 15.
答案 0 :(得分:2)
它将成功覆盖IO :: File :: open,IO :: File :: close但不会覆盖File :: Copy :: move。为什么?的
它会覆盖File::Copy::move
。问题是您不是拨打File::Copy::move
,而是MyCode::move
。因此,您需要使用
local *MyCode::move = sub { ... };
我想知道为什么我会收到[警告
Name "IO::File::close" used only once: possible typo
]。
警告存在以帮助查找拼写错误。在编译期间仅遇到包符号一次时会发出它。在这种情况下,这是一个虚假的警告(就像您禁用的重新定义的警告一样)。
替换
no warnings 'redefine';
与
no warnings 'once';
答案 1 :(得分:1)
使用完整路径(File :: Copy :: move)可以很好地工作。只需要在运行时将'use'更改为'require'即可导入。
use strict;
use warnings;
# use File::Copy;
require File::Copy;
use Errno;
{
no warnings 'redefine';
local *move = sub {
eval {
$! = Errno::EREMMO;
die "oops ($!)";
};
};
File::Copy::move("d:\\swadhi\\perl\\a.txt.bak", "D:\\swadhi\\perl\\bakkkkkup.txt") || print $@;