使用Perl Tkx进行错误处理

时间:2014-12-30 18:02:01

标签: perl error-handling tkx

我正在处理Perl Tkx应用程序,但我无法获得有用/正确的错误消息。我试图使用呱呱声,因此它会告诉我它确切的失败位置,但每次呱呱叫它只是说错误位于"在C:/Perl64/lib/Tkx.pm第347行。"

我写了一个非常简单的脚本来演示正在发生的事情:


#!/usr/bin/perl

use strict;
use warnings;

use Carp;
use Tkx;

my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
    -text => "Hello, world",
    -command => sub { croak; },
);
$b->g_pack;

Tkx::MainLoop();

当我运行此脚本并单击按钮时,我会看到以下弹出框:

croak popup

如何使Tkx处理错误类似于在常规Perl脚本中使用croak?有没有办法强制呱呱打印到STDOUT或STDERR?


修改

迈克尔·卡曼提出了一个很好的观点,即通常使用GUI控制台将被禁止,用户永远不会看到发送到STDOUT或STDERR的错误,但是如何找到一种方法来修改"应用程序错误"对话框说些有用的东西?这可能吗?

该文本不一定必须对最终用户有用,但至少应该是程序员可以理解的,这样他们就知道最终用户报告问题的位置。


EDIT2:

好吧,似乎使用dieconfess代替croak会向"应用程序错误"打印更有用的错误消息。窗口,但一旦我点击" OK"该计划只是继续,并没有实际死亡。我怎么能杀死它直到它死了#34;并确保它死了?


可能的解决方案:

这是Michael Carman的回应建立的可能解决方案。我稍微修改了一下因为我认为messageBox看起来更好一些:)

#!/usr/bin/perl

use strict;
use warnings;

use Tkx;
use Carp;

my $mw = Tkx::widget->new(".");
my $b  = $mw->new_button(
    -text    => "Hello, world",
    -command => sub { die "uh-oh"; },
);
$b->g_pack;

Tkx::eval(<<'EOT');
proc bgerror {message} {
    tk_messageBox -title "Application Error" -message $message -icon error -type ok
    destroy .
}
EOT

Tkx::MainLoop();

到目前为止,这是最好的解决方案,但仍有5天的时间仍然存在,所以请保持这些答案!

2 个答案:

答案 0 :(得分:4)

croak从调用者的角度报告错误。使用die从代码的角度报告错误。

编写模块时通常使用

croak,以便您可以按照代码的使用方式报告问题。 (例如,用于参数验证)GUI编程是一种镜像。您可以将代码注入由其他人编写的库中,而不是为其他人编写库。当您将代码引用传递给-command时,调用方变为Tkx,因此从代码的角度报告任何错误会更好。

Tkx在回调中捕获致命错误,并通过&#34;应用程序错误&#34;报告它们。你正在看的对话。 GUI应用程序与控制台断开连接的情况并不少见,这意味着STDOUT和STDERR已关闭,并且写入它们的任何消息都将丢失。没有对话框,您的应用程序就会消失,用户也不会知道原因。

e.g。

use Tkx;

my $mw = Tkx::widget->new(".");
my $b  = $mw->new_button(
    -text    => "Hello, world",
    -command => sub { die "uh-oh" },
);
$b->g_pack;

Tkx::MainLoop();

当我运行此按钮(并按下按钮)时,对话框消息为

uh-oh at c:\temp\foo.pl line 9.

如果您需要完全控制Tk处理错误的方式,您可以覆盖默认处理程序。问题是你必须在Tcl中完成。这是一个最小版本,用于创建带有错误消息的对话框,并在应用程序关闭时退出。

Tkx::eval(<<'EOT');
proc bgerror {message} {
    tk_dialog .error "Error" $message [] 0 Close
    destroy .
}
EOT

答案 1 :(得分:0)

以下脚本将错误消息打印到STDOUT:

use strict;
use warnings;

use Carp;
use Tkx;

my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
    -text => "Hello, world",
    -command => \&error_test,
);
$b->g_pack;

Tkx::MainLoop();

sub error_test {
    eval {
        confess;
    };
    print "$@\n";
}

输出:

 at ./p.pl line 20.
    eval {...} called at ./p.pl line 19
    main::error_test() called at /home/hakon/perl5/lib/perl5/Tkx.pm line 347
    eval {...} called at /home/hakon/perl5/lib/perl5/Tkx.pm line 347
    Tkx::i::DoOneEvent(0) called at /home/hakon/perl5/lib/perl5/Tkx.pm line 56
    Tkx::MainLoop() called at ./p.pl line 16

修改

以下内容可用于将错误消息打印到Tk GUI的文本字段:

use strict;
use warnings;
use Carp;
use Tkx;

my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
    -text => "Hello, world",
    -command => \&error_test,
);
$b->g_grid(-column => 0, -row => 0);
my $text = $mw->new_tk__text(-width => 100, -height => 30);
$text->g_grid(-column => 0, -row => 1);

Tkx::MainLoop();

sub error_test {
    eval {
        confess;
    };
    print "$@\n";
    $text->insert("end", "$@\n");
}

修改

要在显示错误消息后销毁窗口,您可以使用:

use strict;
use warnings;
use Carp;
use Tkx;

my $mw = Tkx::widget->new(".");
my $b = $mw->new_button(
    -text => "Hello, world",
    -command => \&error_test,
);
$b->g_pack;

Tkx::MainLoop();

sub error_test {
    eval {
        confess;
    };
    Tkx::tk___messageBox(-message => "$@");
    $mw->g_destroy;
}