- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我看到了一些指向 catch block 本身(结束)的异常(参见下面的示例)。
在我看来,这是一个意外的行为,因为它改变了原始异常的位置并且难以调试(应该说死在第 13 行。)
它显示(正确的)第 13 行,如果我使用 die/confess 或使用 eval 而不是 try-catch。
不知道我的代码将如何在堆栈中被调用,我现在开始避免使用 croak。你怎么看?我做对了吗?还是有办法改进?
最好的问候,史蒂夫
use Carp;
use Try::Tiny;
try {
foo();
}
catch {
# do something before die
die $_;
}; # this is line 10
sub foo {
croak 'die'; # this is line 13
}
输出:死于第 10 行。
最佳答案
这是 Carp 的预期行为
[...] use
carp()
orcroak()
which report the error as being from where your module was called. [...] There is no guarantee that that is where the error was, but it is a good educated guess.
所以在调用模块的sub的地方报错,这才是用户想要的
use warnings;
use strict;
use feature 'say';
use Try::Tiny;
package Throw {
use warnings;
use Carp qw(croak confess);
#sub bam { die "die in module" }; # l.11
sub bam { croak "croak in module" };
1;
};
try {
Throw::bam(); # l.17
}
catch {
say "caught one: $_";
die "die in catch: $_";
};
say "done";
打印
caught one: croak in module at exceptions.pl line 17.die in catch: croak in module at exceptions.pl line 17.
If the sub throws using die
then this is reported at line 11
, what is the normal behavior of die, and what you seem to expect.
If any of this is unclear or suboptimal then better use confess
and nicely get a full stacktrace. Also, if you wish more exception-based-like code behavior, can put together an exception/error class and throw its object,† designed and populated as desired.
If you want to confess
an object note that at this time Carp has limits with that
The
Carp
routines don't handle exception objects currently. If called with a first argument that is a reference, they simply calldie()
orwarn()
, as appropriate.
One way then would be to confess
a stringification of the object,‡ getting at least both a full stack backtrace and whatever is in the object.
I get the same behavior with eval
, by replacing try-catch and $_
above
eval {
Throw::bam();
};
if ($@) {
say "caught one: $@";
die "die in catch: $@";
};
打印出来和上面完全一样
虽然上面很清楚并且表现符合预期,但在问题的示例中确实看到了一件奇怪的事情:错误是从整个 try-catch 语句报告的,即。在它的右大括号处,第 10 行所在的位置。 (try
sub 是原型(prototype),整个 try-catch 是一种语法辅助,相当于调用 try
接受匿名 sub,然后可能更多。请参阅 ikegami 的评论和文档。另请参阅 this post 以获取更多关于它的语法。)
这很奇怪,因为对 croaking sub 的调用是 foo()
在try
里面声明和这一行应该被报告,可以通过运行带有 -MCarp::Always
的脚本来确认什么.但是在这个答案的代码中,调用 Throw::bam
的行确实有报道——为什么会有这种差异?
croak
的明确目的将在库中使用,以便用户可以看到他们(用户)代码中的哪一点以触发错误的方式调用了库。 (虽然 die
会指向检测到错误的位置,因此在库中,很可能对用户无用。但请阅读 die
和 Carp
文档以了解相关的复杂性。)
不明显的是当croak
在与 main::foo()
相同的命名空间 ( try-catch
) 中发出在它自己的命名空间(Try::Tiny
)中,事情变得困惑,并报告其声明的结尾。这可以通过添加 foo()
来检查到我上面的代码并调用它(而不是来自模块的子),我们得到了问题的行为重现。
如果 main::foo()
则不会发生这种情况与 croak
inside 是从 main::
中的(复杂)语句调用的,所以这似乎是由于命名空间的 try-catch 混淆。 (另一方面,try-catch 糖向调用堆栈添加了一个匿名子,这肯定也会混淆。)
实际上,我会说:始终使用 croak
在模块之外(否则使用 die
),或者,如果您想模仿基于异常的代码,则更好,使用 confess
和/或您的异常类层次结构。
† 甚至就像die ExceptionClass->new(...);
请记住,在异常方式中,Perl 只有孤独的 die
, 和 eval
.对于更多结构,您需要全部实现,或使用像 Exception::Class 这样的框架或 Throwable
‡ 通过编写和使用一种方法,该方法可以生成包含来自对象的有用信息的纯字符串,对于 Carp::confess $obj->stringify
.
或通过overloading ""
该类的(引用)运算符,因为它在 confess
时被使用-ing 对象(字符串上下文),用于 Carp::confess $obj
;无论如何,这很好。
两者的基本示例:
use overload ( q("") => \&stringify );
sub stringify {
my $self = shift;
join ", ", map { "$_ => " . ( $self->{$_} // 'undef' ) } keys %$self
}
可以直接写一个匿名 sub
而不是对命名子的引用.
关于Perl 意外行为 : croak vs. try catch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66527342/
如果我的 Perl 程序使用 Perl 模块,它将如何确定在哪里可以找到包含模块代码的文件? 例如,如果程序包含: use MyModule1; # Example 1 us
我在一个文件中有一些不同格式的数字:8.3、0.001、9e-18。我正在寻找一种简单的方法来读取它们并存储它们而不会损失任何精度。这在 AWK 中很容易,但在 Perl 中是如何完成的呢?我只愿意使
我在一个文件中有一些不同格式的数字:8.3、0.001、9e-18。我正在寻找一种简单的方法来读取它们并存储它们而不会损失任何精度。这在 AWK 中很容易,但在 Perl 中是如何完成的呢?我只愿意使
我正在自学 Perl,并且在我的 Windows 8 64 位系统上安装了 Strawberry。 Strawberry 命令行似乎工作正常,我在 C 驱动器上的 Strawberry 文件夹中创建了
我在 Perl 模块 IO::Socket::SSL 中发现了一个错误,我可能会修复它,但是,我担心测试修复。我从 Debian 下载了源码包(因为我打算为它制作一个 Debian 包或补丁)并查看了
我有一个 perl 文件,它使用了两个 perl 模块 A.pm 和 B.pm。 但是在 B.pm 中我需要调用 A.pm 的子程序。即使我在 A.pm 中使用并尝试使用它,我仍然遇到未定义的错误。
有没有办法在 Perl 运行时加载整个模块?我原以为我用 autouse 找到了一个很好的解决方案,但以下代码无法编译: package tryAutouse2; use autouse 'tryAu
过去,我编写过许多 perl 模块,以及不止一些独立的 perl 程序,但我之前从未发布过多文件 perl 程序。 我有一个几乎处于 beta 阶段的 perl 程序,它将被开源发布。它需要一些数据文
我有 1 个 perl 脚本,我们在其中编写了几个子例程。例子: # Try_1.pl main(); sub main{ --- --- check(); } check { -- --} 现在,
似乎 CPAN 上的一些(很多?)模块部分是使用 XS 在 C 中实现的,如果需要,可以回退到纯 perl 实现。虽然这很聪明,但它显然会损害性能,我想知道它是否会发生,以便我可以解决问题。 有没有一
我对 perl 很陌生。我希望我可以从 perl 安装一些软件包,我这样做是这样的: perl -MCPAN -e 'install VM::EC2' 我猜它由于依赖而失败,它显示: Result:
给定一个 Perl 包 Foo.pm,例如 package Foo; use strict; sub bar { # some code here } sub baz { # more
我有一个用 Perl 编写的测试生成器。它生成连接到模拟器的测试。这些测试本身是用 Perl 编写的,并通过其 API 连接到模拟器。我希望生成的代码是人类可读的,这意味着我希望它能够正确缩进和格式化
我正在学习 Perl,非常新的用户。我可以知道这些 Perl 代码之间有什么区别吗? #!/usr/bin/perl & #!/usr/bin/perl -w 最佳答案 那不是 perl 代码,它是
我不认为这是一个重复的问题。这专门针对 Perl 模块附带的脚本。 通常,在安装多个 Perl 版本时,您可以将 perl 可执行文件标记为版本号 (perl5.32),这样它们就可以在 /whate
我有一个在文件中使用 Blowfish 加密的程序和第二个 perl 程序,它提示输入用于将其解密为字符串的密码,我希望不必将解密的源代码写入硬盘驱动器,尽管将它放在内存中并不是真正的问题,因为运行程
有没有人为 Perl 中的惰性求值列表找到了一个好的解决方案?我尝试了很多方法来改变类似的东西 for my $item ( map { ... } @list ) { } 进入懒惰的评估——例如,通
我安装了多个版本的 Perl。 我已经指定了要使用的版本。但是为了验证,我想从 .pl 脚本本身输出 Perl 的版本。 这可能吗? 在 Perl 脚本中解析“perl --version”的输出似乎
人们还经常问“我怎样才能编译 Perl?”而他们真正想要的是创建一个可以在机器上运行的可执行文件,即使他们没有安装 Perl。 我知道有几种解决方案: perl2exe靛蓝之星 它是商业的。我从未尝试
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它. 8年前关闭。 Improve this
我是一名优秀的程序员,十分优秀!