【问题标题】:Perl how to catch two exceptions thrown at oncePerl如何捕获一次抛出的两个异常
【发布时间】:2013-04-03 19:38:33
【问题描述】:

我正在解析一个大型 EMBL 文件 (>1G) 并将其转换为 gff 文件。它有一些条目与传统的 embl 格式不匹配,因此导致 bioperl 模块抛出异常。我的问题是因为有错误的条目只是总序列的一小部分,我想继续脚本,暂时忽略异常。但是 perl 脚本总是被异常停止。

我在 linux 操作系统下使用 perl 版本 5.8.8

我的 perl 脚本

use strict;
use Bio::SeqIO;
use Bio::Tools::GFF;
use warnings;
use Try::Tiny;

open (E ,">","emblError.txt");

if (@ARGV != 1) {    die "USAGE: embl2gff.pl   > outputfile.\n"; }

my $in = Bio::SeqIO->new(-file=>$ARGV[0],-format=>'EMBL');
eval {
   while (my $seq = $in->next_seq) {
      for my $feat ($seq->top_SeqFeatures) {
          my $gffio = Bio::Tools::GFF->new(-gff_version => 3);
          print $feat->gff_string($gffio)."\n";
        }
    }
};
if ($@) {
    warn "Oh no! [$@]\n";
}

我得到的错误

Name "main::E" used only once: possible typo at embl2GFF3.pl line 7.

--------------------- WARNING ---------------------
MSG: exception while parsing location line [join(9174..9343,14214..14303)complement(9268..9363),complement(9140..9198),complement(8965..9034),complement(8751..8884),complement(8419..8535),complement(8232..8337),complement(7952..8149),complement(7256..7332),complement(7051..7175),complement(6769..6877),complement(6601..6659),complement(4690..6530))] in reading EMBL/GenBank/SwissProt, ignoring feature mRNA (seqid=XcouVSXmac70forkSpecies.Scaffold1050.final):
------------- EXCEPTION: Bio::Root::Exception -------------
MSG: Bad operator 1: had multiple locations 2, should be SplitLocationI
STACK: Error::throw
STACK: Bio::Root::Root::throw /usr/lib/perl5/site_perl/5.8.8/Bio/Root/Root.pm:472
STACK: Bio::Factory::FTLocationFactory::from_string /usr/lib/perl5/site_perl/5.8.8/Bio/Factory/FTLocationFactory.pm:210
STACK: Bio::Factory::FTLocationFactory::from_string /usr/lib/perl5/site_perl/5.8.8/Bio/Factory/FTLocationFactory.pm:204
STACK: Bio::SeqIO::FTHelper::_generic_seqfeature /usr/lib/perl5/site_perl/5.8.8/Bio/SeqIO/FTHelper.pm:133
STACK: Bio::SeqIO::embl::next_seq /usr/lib/perl5/site_perl/5.8.8/Bio/SeqIO/embl.pm:403
STACK: embl2GFF3.pl:14
-----------------------------------------------------------

---------------------------------------------------

--------------------- WARNING ---------------------
MSG: exception while parsing location line [join(14219..14303,14368..14513)complement(9140..9198),complement(8965..9034),complement(8751..8884),complement(8419..8535),complement(8232..8337),complement(7952..8149),complement(7256..7332),complement(7051..7175),complement(6769..6877),complement(6601..6659),complement(6461..6530))] in reading EMBL/GenBank/SwissProt, ignoring feature CDS (seqid=XcouVSXmac70forkSpecies.Scaffold1050.final):
------------- EXCEPTION: Bio::Root::Exception -------------
MSG: Bad operator 1: had multiple locations 2, should be SplitLocationI
STACK: Error::throw
STACK: Bio::Root::Root::throw /usr/lib/perl5/site_perl/5.8.8/Bio/Root/Root.pm:472
STACK: Bio::Factory::FTLocationFactory::from_string /usr/lib/perl5/site_perl/5.8.8/Bio/Factory/FTLocationFactory.pm:210
STACK: Bio::Factory::FTLocationFactory::from_string /usr/lib/perl5/site_perl/5.8.8/Bio/Factory/FTLocationFactory.pm:204
STACK: Bio::SeqIO::FTHelper::_generic_seqfeature /usr/lib/perl5/site_perl/5.8.8/Bio/SeqIO/FTHelper.pm:133
STACK: Bio::SeqIO::embl::next_seq /usr/lib/perl5/site_perl/5.8.8/Bio/SeqIO/embl.pm:403
STACK: embl2GFF3.pl:14
-----------------------------------------------------------

---------------------------------------------------
Oh no! [Can't call method "isa" on an undefined value at /usr/lib/perl5/site_perl/5.8.8/Bio/Seq.pm line 1142, <GEN0> line 538764.
]

注意:我没有两次发布异常,它只是以这种方式发生,似乎只有一个异常被捕获。

这是导致问题的 embl 文件块。 mRNA 进入导致第一个异常,CDS 导致第二个异常。

FT   mRNA            join(9174..9343,14214..14303)
FT                   complement(9268..9363),complement(9140..9198),
FT                   complement(8965..9034),complement(8751..8884),
FT                   complement(8419..8535),complement(8232..8337),
FT                   complement(7952..8149),complement(7256..7332),
FT                   complement(7051..7175),complement(6769..6877),
FT                   complement(6601..6659),complement(4690..6530))
FT                   /gene="ENSXMAG00000014948"
FT                   /note="transcript_id=ENSXMAT00000015030"
FT   CDS             join(14219..14303,14368..14513)
FT                   complement(9140..9198),complement(8965..9034),
FT                   complement(8751..8884),complement(8419..8535),
FT                   complement(8232..8337),complement(7952..8149),
FT                   complement(7256..7332),complement(7051..7175),
FT                   complement(6769..6877),complement(6601..6659),
FT                   complement(6461..6530))
FT                   /gene="ENSXMAG00000014948"
FT                   /protein_id="ENSXMAP00000015010"
FT                   /note="transcript_id=ENSXMAT00000015030"
FT                   /db_xref="HGNC_transcript_name:ENO3-201"

【问题讨论】:

  • 您需要向我们展示代码。
  • 对不起,我打错了,脚本和例外都列出来了

标签: perl exception eval bioperl


【解决方案1】:

eval 不会捕获低级 Perl 错误。还要检查$SIG{__DIE__} 处理程序。如果一个 die-handler 写得不熟练,它可能就死了。例如,如果处理程序不检查$EXCEPTIONS_BEING_CAUGHT,它可能会来自模具处理程序的exit

但只要看看你的输出,如果它打印了这个:

Oh no! [Can't call method "isa" on an undefined value at 
/usr/lib/perl5/site_perl/5.8.8/Bio/Seq.pm line 1142, line 538764. ]

那么,它并没有按照你所说的那样做。您的eval 发现了错误,否则您将无法在前面加上"Oh no!" 打印它。看起来它自己做了一些堆栈跟踪转储。

最后,您的程序状态看起来是依赖于数据的,并且您的文件中的一些错误值可能会将其置于错误状态。无论出于何种原因,它都无法创建 BIO::Seq 对象并将其传递给某个函数,该函数检查参数 isa 是否存在。看起来您输入文件中的违规行是#538,764。但我可能是错的。

注意:解决您在 cmets 中的问题。如果 Bioperl 正在处理它发现的错误,而您只想浏览一系列记录,那么我的建议是您将 eval inside 放在循环中——whilefor 循环。对于某些多线程应用程序来说,这是一种非常标准的形式。

 while ( 1 ) {
     eval { $me->spin(); 1; } or say "WARNING: $@";
     # unless we are officially done, just get ready to
     # handle somebody causing an exception in our thread.
     last if $me->done; 
 }

如果可能,请记住将eval 放在要恢复处理的位置。

【讨论】:

  • 你真快。我已经发布了脚本(我之前打错了底部),你介意更具体一点吗?谢谢。
  • 它一次抛出两个异常,也许只有一个被捕获?如果是这样,我可能应该更改标题。
  • @user2241994,它可能会在后台抛出 20 个错误,然后捕获并从中恢复,但您只会看到一个错误,以 "Oh no! [$@]\n" 格式打印。所以它被抓住了。 Bioperl 模块只是详细地帮助您。你有最前沿的 Bioperl 或模块吗?如果不是,我不禁觉得你应该找出输入行的样子。
  • 谢谢。 seqIO 和 GFF 模块是相当标准的模块。 embl 文件是由 RATT(快速注释传输工具)程序生成的,我知道可能有很多错误。我最终会做一些事情来修复这些错误,但现在我知道 >95% 的序列是正确的,我想得到这些序列,这样实验室里的人就会有一个项目要做。我的问题是如何忽略错误(无论有多少)并继续。
  • @user2241994,我猜你的eval 和处理程序inside while--或for 循环。这样它就会产生错误并继续运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
  • 1970-01-01
  • 2013-06-24
  • 1970-01-01
  • 2010-10-03
相关资源
最近更新 更多