`最后读取外部命令崩溃的文件时perl
我有以下代码:
#!/usr/bin/env perl
use 5.0360;
use warnings FATAL => 'all';
use autodie ':default';
use Devel::Confess 'color'; # not essential, but better error reporting
open my $view, "zcat a.big.file.vcf.gz|"; # zcat or bcftools
while (<$view>) {
next unless /^#CHROM\t/;
last;
}
close $view;
上面的代码崩溃了
Can't close(GLOB(0x55adfa96ebf8)) filehandle: '' at (eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683] line 74
at (eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683] line 74.
main::__ANON__[(eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683]:86](GLOB(0x55adfa96ebf8)) called at mwe.pl line 13
Command exited with non-zero status 255
,但是,如果我评论上次
代码运行没有问题,则该文件为 gumet ,这使得运行时间有显着差异。
如果我删除关闭$ view
,则代码也有效,但是CLOSE
是正确的练习。
如何使用last
和关闭$ view
运行代码?
I have the following code:
#!/usr/bin/env perl
use 5.0360;
use warnings FATAL => 'all';
use autodie ':default';
use Devel::Confess 'color'; # not essential, but better error reporting
open my $view, "zcat a.big.file.vcf.gz|"; # zcat or bcftools
while (<$view>) {
next unless /^#CHROM\t/;
last;
}
close $view;
the above code crashes with the error
Can't close(GLOB(0x55adfa96ebf8)) filehandle: '' at (eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683] line 74
at (eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683] line 74.
main::__ANON__[(eval 11)[/home/con/perl5/perlbrew/perls/perl-5.36.0/lib/5.36.0/Fatal.pm:1683]:86](GLOB(0x55adfa96ebf8)) called at mwe.pl line 13
Command exited with non-zero status 255
However, if I comment out last
the code runs without a problem, however, the file is huge and this makes a significant difference in running time.
The code also works if I remove close $view
but close
is proper practice.
How can I run the code with both last
and close $view
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当您
最后
读取该过程(zcat
在此处)和关闭管道,在过程完成之前,该过程获取sigpipe
因此
close> close> close
然后等待
s上它获得非零,并返回false(如下所示)。就这样。其余的 - 程序“崩溃” - 最多可autodie
,它引发了异常。没有autodie
(或致命警告)我获得
命令退出状态:13
,关闭 $!$! /代码>是错误的。这表明唯一的问题是非零状态我们确实收到了一个信号,
13
(对于sigpipe
,请参见Man 7 Signal
),哪些终止程序,因此没有特定的退出代码($?&gt;&gt; 8
的确是零),并且没有抛弃核心($?&amp; 128
是零)。请参阅 $?在perlvar因为退出状态为非零
关闭
返回false和autodie
引发其异常。那该怎么办?
当然,
关闭
必须保留并检查。即使
sigpipe
发送到zcat
的也可以忽略作者知道没有读者可以停止!最后,杀死程序的
autodie
可以通过词法禁用。 (这满足了评论中指定的autodie
的“需求”。)因此,将此管道读数放在块中,请不要忘记在此代码中适当调整您的其他错误处理。
(我在
no autodie
“泄漏”范围中有奇怪的经历,请参见在这里。
CLOSS()
,在eval
中而是。他们在文档中说,这被认为是好的做法。然后查看如何使用 autodie Exceptions 。When you
last
out of reading that process (zcat
here) and close the pipe, before the process is done writing, the process gets aSIGPIPE
So as
close
thenwait
s on it it gets a non-zero, and returns false (as seen below). That's all. The rest -- the program "crashing" -- is up toautodie
, which throws an exception. Withoutautodie
(or fatal warnings)I get
Command exit status: 13
, soclose
didn't return true while$!
is false. This indicates that the only issue was the non-zero statusWe did get a signal,
13
(forsigpipe
, seeman 7 signal
), what terminated the program and so there was no particular exit code ($? >> 8
is indeed zero), and no core was dumped ($? & 128
is zero). See $? in perlvarSince the exit status is non-zero
close
returns false andautodie
throws its exception.So what to do with this?
That
close
must stay and be checked, of course.Even if the
SIGPIPE
sent tozcat
could be ignored, as I've seen claimed in some docs, you wouldn't want that -- it's there on purpose, to let the writer know that there are no readers so that it can stop!Finally, it is
autodie
that kills the program, and it can be disabled lexically. (This satisfies the "need" forautodie
stated in a comment.) So put this pipe reading and early close in a blockDon't forget to suitably adjust your other error handling in this code.
(I've had weird experience with
no autodie
"leakage" out of its scope, see here. But that was a different case, and fixed byautodie
2.30 so hopefully not of concern.)Another option is to wrap all this, or just the
close()
, ineval
instead. This is considered good practice, they say in docs. Then see how to work with autodie exceptions.