使用Try and Catch移动错误

时间:2016-06-29 18:03:45

标签: perl

这是我的第一个问题,所以如果我格式化/问错了,我会提前道歉。

我使用Perl从文件中提取字符串,提交Web表单,并下载由网页创建的新文件。目的是让它在循环中运行30,000个文件,我估计需要大约8天。我正在使用WWW :: Selenium和WWW :: Mechanize来执行Web自动化。我遇到的问题是,如果由于某种原因页面没有正确加载或互联网丢失了一段时间,那么脚本会退出并给出一个错误消息(取决于它失败的阶段):

Error requesting http://localhost:4444/selenium-server/driver/:
ERROR: Could not find element attribute: link=Download PDB File@href

我希望脚本继续运行,进入下一轮循环,所以我不必担心如果一轮循环抛出错误。我的研究表明,使用Try::Tiny可能是最好的解决方案。目前我只使用try{...}使用下面的脚本,这似乎可以抑制任何错误并允许脚本继续浏览文件。但是,我担心这似乎是一个非常直率的解决方案,并且无法让我了解文件失败的原因/原因。

理想情况下,我希望将每个出现的文件名和错误消息打印到另一个文件,然后在脚本完成后再进行审核,但我很难理解如何使用catch{...}来执行此操作或者甚至是正确的解决方案。

use strict;
use warnings;
use WWW::Selenium;
use WWW::Mechanize;
use Try::Tiny;


my @fastas = <*.fasta>;
foreach my $file (@fastas) {
try{

open(my $fh, "<", $file);
my $sequence;
my $id = substr($file, 0, -6);
while (my $line = <$fh>) {

        ## discard fasta header line
        } elsif($line =~ /^>/) {     # / (turn off wrong coloring)
            next;

        ## keep line, add to sequence string
        } else {
            $sequence .= $line;
        }
    }
close ($fh);

my $sel = WWW::Selenium->new( host => "localhost",
                              port => 4444,
                              browser => "*firefox",
                              browser_url => "http://www.myurl.com",
                            );

$sel->start;
$sel->open("http://www.myurl.com");
$sel->type("chain1", $sequence);
$sel->type("chain2", "EVQLVESGPGLVQPGKSLRLSCVASGFTFSGYGMHWVRQAPGKGLEWIALIIYDESNKYYADSVKGRFTISRDNSKNTLYLQMSSLRAEDTAVFYCAKVKFYDPTAPNDYWGQGTLVTVSS");
$sel->click("css=input.btn.btn-success");
$sel->wait_for_page_to_load("30000");

## Wait through the holding page - will timeout after 5 mins
$sel->wait_for_element_present("link=Download PDB File", "300000");
## Get the filename part of link
$sel->wait_for_page_to_load("30000");
my $pdbName = $sel->get_attribute("link=Download PDB File\@href");
## Concatenate it with the main domain
my $link = "http://www.myurl.com/" . $pdbName;
$sel->stop;

my $mech = WWW::Mechanize->new( autocheck => 1 );
$mech -> get($link);
#print $mech -> content();
$mech -> save_content($id . ".pdb");
};

}

1 个答案:

答案 0 :(得分:4)

您想要查看,记录和查看所有错误(和警告)是完全正确的。 Try::Tiny提供的机制和语法是简单易用的。

use feature qw(say);

my $errlog = 'error_log.txt';
open my $fh_err, '>', $errlog  or die "Can't open $errlog for writing: $!";

foreach my $file (@fastas) {
    try {
        # processing, potentially throwing a die
    }
    catch {
        say $fh_err "Error with $file: $_";   # NOTE, it is $_ (not $! or $@)
    };
}
close $fh_err;

# Remove the log if empty
if (-z $errlog) { 
    say "No errors logged, removing $errlog";
    unlink $errlog or warn "Can't unlink $errlog: $!";
}    

您可以在push @failed_files, $file块内部catch { }保存处理失败的文件的名称。然后代码可以在主处理之后再次尝试,如果您知道错误主要是由于随机连接问题。拥有失败文件列表非常方便。

请注意,对于v5.14,此模块会解决were fixed的问题,以便正常使用eval。在这一点上,这主要是一个偏好问题,但请注意Try::Tiny有一些自己的曲折。有关讨论,请参阅this post

这解决了简单异常处理的问题,而不是代码的其余部分。