Поймать исключение команды оболочки в Perl 6 - PullRequest
0 голосов
/ 01 октября 2018

Мне пришлось запустить программу оболочки, завершающуюся с ошибкой из Perl 6, поэтому я решил проверить, как она работает.Я создал скрипт bash, выдающий ошибку для его запуска из программы на Perl 6:

$ cat prog.sh 
echo "error" >&2
exit 1

Вот как я его называю из Perl 6:

put "start";
  try {
    shell "./prog.sh";
  }
put "end";

вывод показывает, что программа закрылась после запуска команды оболочки.

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

Если я добавлю CATCH блок

put "start";
  try {
    shell "./prog.sh";
    CATCH { default {} }
  }
put "end";

все в порядке, и программа будет работать до последней строки:

start
error
end

Так что мойвопрос: почему необходимо добавить блок CATCH, в то время как try сам по себе не может устранить ошибку?

1 Ответ

0 голосов
/ 02 октября 2018

shell не выбрасывает Exception до тех пор, пока sink.

Блок try, содержащий только shell, полностью выполняется без исключения.будучи брошенным, возвращает последнее значение в блоке, которое затем западает вне контекста try, который затем выбрасывает Exception.

. Вы можете увидеть это с помощью:

put "start";
  try {
    shell "./prog.sh";
    'something';
  }
put "end";

Теперь оболочка погружается в try, который попадает в неявное CATCH из try.Блок try возвращает последнее значение в блоке, «что-то», которое затем безопасно удаляется за пределы try.

. Вы также можете заставить sink произойти внутри try:

put "start";
try {
   sink shell "./prog.sh"
}
put "end";

Ваш добавленный блок CATCH просто препятствует тому, чтобы блок try возвращал возвращаемое значение из shell.

Вы можете изменить их расположение и увидеть, чтоэто все еще взрывается:

put "start";
try {
    CATCH { default {} }
    shell "./prog.sh";
}
put "end";

Лучший, самый ясный способ справиться с этим ИМХО - это проверить возвращение из оболочки самостоятельно, а не дать ему опуститься и выдать исключение:

put "start";
if shell "./prog.sh" {
    say 'ok'
}
else {
    say 'failed'
}
put "end";
...