Perl 子例程如何报告调用它的行?
How can a Perl subroutine report the line that called it?
我正在编写一个 Perl 管道,这是一个调用各种其他程序并管理从一个程序到另一个程序的数据传递的脚本。该脚本(称之为 pipeline.pl
)及其管理的各种子脚本都共享一个在 subroutines.ph
中定义并通过 require subroutines.ph
指令包含的公共子例程列表。
其中一个是一个函数,它的工作是退出打印错误消息(实际的子例程还做一些其他的工作,但它们在这里不相关;不,我不是重新发明 die()
) :
## subroutines.ph
sub errorDie
{
my ($errMsg) = @_;
## various other cleanup tasks here
die($errMsg);
}
1;
并且,在 pipeline.pl
中:
#!/usr/bin/perl
require 'subroutines.ph';
errorDie("foo")
运行 上面的脚本导致:
foo at subroutines.ph line 5.
是否可以让它报告如下内容:
foo at pipelines.pl line 4.
因此,与其报告找到 die()
的行,不如报告调用 errorDie
子例程的原始脚本的行。我知道我可以通过在 $errMsg
变量中包含该行来做到这一点,但这很脆弱而且很麻烦。这可以自动完成吗?外部文件中定义的子例程能否检测到它是从哪里调用的?
有 caller
,要做到这一点:
https://perldoc.perl.org/functions/caller.html
my ($package, $filename, $line) = caller;
为您提供所需的信息。
但是,正如您所说的一般调试,您可以从 carp
获得完整的回溯,如前所述。
这就是 Carp 的 croak
的重点。
Pkg.pm
:
package Pkg;
use Carp qw( croak );
sub some_func {
my ($cmd, $param) = @_;
$cmd eq 'encode' || $cmd eq 'decode'
or croak("Invalid command \"$cmd\"");
# ...
}
1;
a.pl
:
use Pkg;
Pkg::some_func('foo', 'bar');
输出:
Invalid command "foo" at a.pl line 3.
我正在编写一个 Perl 管道,这是一个调用各种其他程序并管理从一个程序到另一个程序的数据传递的脚本。该脚本(称之为 pipeline.pl
)及其管理的各种子脚本都共享一个在 subroutines.ph
中定义并通过 require subroutines.ph
指令包含的公共子例程列表。
其中一个是一个函数,它的工作是退出打印错误消息(实际的子例程还做一些其他的工作,但它们在这里不相关;不,我不是重新发明 die()
) :
## subroutines.ph
sub errorDie
{
my ($errMsg) = @_;
## various other cleanup tasks here
die($errMsg);
}
1;
并且,在 pipeline.pl
中:
#!/usr/bin/perl
require 'subroutines.ph';
errorDie("foo")
运行 上面的脚本导致:
foo at subroutines.ph line 5.
是否可以让它报告如下内容:
foo at pipelines.pl line 4.
因此,与其报告找到 die()
的行,不如报告调用 errorDie
子例程的原始脚本的行。我知道我可以通过在 $errMsg
变量中包含该行来做到这一点,但这很脆弱而且很麻烦。这可以自动完成吗?外部文件中定义的子例程能否检测到它是从哪里调用的?
有 caller
,要做到这一点:
https://perldoc.perl.org/functions/caller.html
my ($package, $filename, $line) = caller;
为您提供所需的信息。
但是,正如您所说的一般调试,您可以从 carp
获得完整的回溯,如前所述。
这就是 Carp 的 croak
的重点。
Pkg.pm
:
package Pkg;
use Carp qw( croak );
sub some_func {
my ($cmd, $param) = @_;
$cmd eq 'encode' || $cmd eq 'decode'
or croak("Invalid command \"$cmd\"");
# ...
}
1;
a.pl
:
use Pkg;
Pkg::some_func('foo', 'bar');
输出:
Invalid command "foo" at a.pl line 3.