gpt4 book ai didi

perl - 不确定我是否正确使用了 Perl 的 Try::Tiny

转载 作者:行者123 更新时间:2023-12-02 08:45:29 25 4
gpt4 key购买 nike

我刚开始使用对象,不明白为什么 Try::Tiny不会 catch 我的 try 语句中的错误。这是我正在尝试做的示例:

use strict;  
use warnings;
use Net::FTP;
use Try::Tiny;

my $TIMEOUT = 5;
my $HOST = 'replace_with_hostname';
my $USER = 'replace_with_username';
my $PASS = 'replace_with_password';
my @ERRORS;
my $ftp = undef;

sub my_sub {
my $err = shift;
push(@ERRORS,$err);
goto END;
}

try {
local $SIG{ALRM} = sub { die "new\n" };
alarm $TIMEOUT;
$ftp = Net::FTP->new($HOST, Passive=>1, DEBUG=>3, Timeout=>2);
alarm 0;
}
catch {
die $_ if $_ ne "new\n";
my_sub("FTP: cannot connect to [$HOST]");
};

try {
local $SIG{ALRM} = sub { die "login\n" };
alarm $TIMEOUT;
$ftp->login($USER,$PASS);
alarm 0;
}
catch {
die $_ if $_ ne "login\n";
my_sub("FTP: cannot cannot log in");
};

END: {
if (@ERRORS) {
print "$ERRORS[0]\n";
exit -1;
}
print "Success\n";
exit 0;
}

我正在使用 goto 函数,因为我最终会有用于 WebDAV 和 CMIS 测试的 block ,并且希望在我点击 END 之前捕获所有错误。我可以通过像这样更改 try-catch block 来让前面的做我想做的事:

try {
local $SIG{ALRM} = sub { die "new\n" };
alarm $TIMEOUT;
$ftp = Net::FTP->new($HOST, Passive=>1, DEBUG=>3, Timeout=>2)
or my_sub("FTP: cannot connect to [$HOST]");
alarm 0;
}
catch {
die $_ if $_ ne "new\n";
};

但是,在这两种情况下,我都觉得我没有使用 Try::Tiny出色地。

当然,我真正想做的是将 try-catch block 放在一个函数中,就像 sid_com did .这对我不起作用:

sub try_f {
my $cmd = shift;
my $msg = shift;
try {
local $SIG{ALRM} = sub { die "timeout '$cmd'\n" };
alarm $TIMEOUT;
\$cmd or my_sub($msg);
alarm 0;
}
catch {
die $_ if $_ ne "timeout '$cmd'\n";
};
} # sub

try_f("$ftp = Net::FTP->new(Host=>$HOST, Passive=>1)", "FTP: cannot connect to [$HOST]");

try_f("$ftp->login($USER,$PASS)", "FTP: cannot cannot log in");

错误提示 $ftp 是一个未初始化的值,但我不知道如何解决这个问题。

编辑:这是我收到的两个答案的工作综合。谢谢,Max 和 LeoNerd!

use strict;  
use warnings;
use Net::FTP;
use Try::Tiny;

my $HOST = 'replace_with_hostname';
my $USER = 'replace_with_username';
my $PASS = 'replace_with_password';
my @ERRORS;
my $ftp = undef;

sub try_f {
my $timeout = shift;
my $command = shift;
my $message = shift;
my $label = shift;
try {
local $SIG{ALRM} = sub { die "timeout\n" };
alarm $timeout;
$command->() or die "module\n";
alarm 0;
}
catch {
if ( $_ eq "module\n" || $_ eq "timeout\n" ) {
push(@ERRORS,"$message: $_");
goto $label;
}
die $_;
};
}

FTP_BLOCK: {
try_f(4, sub { $ftp = Net::FTP->new($HOST, Passive=>1, Debug=>3) }, "FTP: cannot connect to [$HOST]", 'END');
try_f(2, sub { $ftp->login($USER,$PASS) }, "FTP: cannot log in", 'END');
}

END: {
if (@ERRORS) {
foreach my $e (@ERRORS) { print "$e"; }
exit -1;
}
print "Success\n";
exit 0;
}

最佳答案

Net::FTP->new不会因错误死亡。相反,它只是返回 undef。因此,Try::Tiny 无法确定出现了什么问题,并且 catch block 不会被执行。

代替my_sub,使用

$ftp = Net::FTP->new($HOST, Passive=>1, DEBUG=>3, Timeout=>2) or die $@;

Try::Tiny 文档说 $@ 不会有错误catch block ,但是 Net::FTP->new 表示如果它返回 undef,它将在此处放置一条错误消息。这就是为什么您可以 die try block 中使用该消息(如果需要,您也可以在这种情况下使用自己的消息)。

同样,登录 returns a false value on error ,因此您需要添加“or die”语句(不幸的是,login 似乎不会在出错时给出错误消息)。

关于perl - 不确定我是否正确使用了 Perl 的 Try::Tiny,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12788884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com