在Perl 6中捕获shell命令的异常

Eug*_*sky 8 perl6

我不得不运行一个shell程序退出并出现Perl 6的错误,所以我决定测试它是如何工作的.我做了一个bash脚本产生错误,从Perl 6程序运行它:

$ cat prog.sh 
echo "error" >&2
exit 1
Run Code Online (Sandbox Code Playgroud)

以下是我从Perl 6中调用它的方法:

put "start";
  try {
    shell "./prog.sh";
  }
put "end";
Run Code Online (Sandbox Code Playgroud)

输出显示程序在运行shell命令后退出.

start
error
The spawned command './prog.sh' exited unsuccessfully (exit code: 1)
  in block <unit> at b.p6 line 2
Run Code Online (Sandbox Code Playgroud)

如果我添加一个CATCH

put "start";
  try {
    shell "./prog.sh";
    CATCH { default {} }
  }
put "end";
Run Code Online (Sandbox Code Playgroud)

一切都很好,程序工作到最后一行:

start
error
end
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:为什么有必要添加CATCH块,而try本身无法解决错误?

Cur*_*mes 9

shell不会扔到Exception直到sink.

try只有shellin中的块完全执行而没有抛出异常,返回块中的最后一个值,然后在该上下文之外沉没try,然后抛出Exception.

你可以看到这个:

put "start";
  try {
    shell "./prog.sh";
    'something';
  }
put "end";
Run Code Online (Sandbox Code Playgroud)

现在shell陷入了内部try,它被隐含CATCH的内容所捕获try.该try块返回块中的最后一个值,即"某事物",然后安全地沉入其中try.

你也可以强迫它sink发生在try:

put "start";
try {
   sink shell "./prog.sh"
}
put "end";
Run Code Online (Sandbox Code Playgroud)

你添加的CATCH块只是阻止try块从中返回返回值shell.

你可以重新安排它们,看看它仍然会爆炸:

put "start";
try {
    CATCH { default {} }
    shell "./prog.sh";
}
put "end";
Run Code Online (Sandbox Code Playgroud)

处理这个恕我直言的最好,最明确的方法是自己检查shell的返回,而不是让它下沉并抛出异常:

put "start";
if shell "./prog.sh" {
    say 'ok'
}
else {
    say 'failed'
}
put "end";
Run Code Online (Sandbox Code Playgroud)

  • `shell`返回一个`Failure`,它是一个`Exception`的包装器.只有当"失败"实际被使用或沉没时,它才会"抛出"它所包裹的"异常".你可以**在`Failure`上调用`.defined`或`.Bool`而不抛出它:如果你在`if`中使用它就会发生`.Bool`,这是Curt在​​最后一个代码中显示的内容例. (5认同)
  • 是.并且`.defined`适用于你想在`with`块中使用它的时候. (2认同)