2013-06-25 4 views
9

Большинство времени, я сделать что-то вроде этого:Следует ли умереть, если открытие файла не удалось?

open FH, ">file.txt" or die "Cann't open file: $!"; 

ли должны использоваться die? Если я хочу, чтобы мой скрипт продолжал (и просто игнорировал ошибку, если файл не может быть открыт), что мне делать?

+3

Пожалуйста, не используйте Barewords 'FH' или 2 Аргумент путь открыт. ВСЕГДА используйте 'open my $ fh, '>', 'file.txt''. Это безопаснее, потому что Barewords являются глобальными. Также с возможностью открытия (чтение, добавление, письмо, ..). Когда вы используете переменную для имени файла, она может начинаться с чего-то ненадежного, сомнительного (например, Pipe ...) =) –

+3

Пожалуйста, никогда не делайте подобные заявления. То, что он делает это прекрасно, во многих ситуациях. – tchrist

ответ

20

Вы можете захотеть сделать что-то вроде

if(open my $fh, ">", "file.txt") { 
    # do stuff with file 
    close $fh; 
} 
else { 
    # do stuff without file 
} 
+0

В остальном, хорошо ли мне использовать goto (например, goto Exit и в конце скрипта Exit: exit (-1);)? – ericyoung

+6

@ericyoung - Нет. Нет, это не так. Вам будет намного лучше, если вы притворитесь, что у Perl нет реализации 'goto'. И вы всегда можете делать 'open (my $ fh,"> "," file.txt ") или exit (-1);' –

+0

@JackManey: На самом деле это не совсем так. Версия 'goto & SUB'' goto' действительно полезна :-) –

-1

Вы можете использовать блок catch try, используя Try :: Tiny или что-то в этом роде.

+2

пока я не сделал -1, IMO это комментарий, а не ответ .. и это звучит немного pythonic, а не perlis ... – Aprillion

+0

я тоже не сделал -1, но OP хочет игнорировать ошибки и открыть () по умолчанию не умирает, поэтому это даже не ответ, если только OP не использует autodie, что было бы глупо, если он хочет игнорировать ошибки. – runrig

+0

@deathapril Вы правы, что это не perlish при условии, что это 1998. – darch

8

Код не содержит die, если он не может получить доступ к файлу.

Если запись в файл не является обязательным, вы можете сделать что-то вроде этого:

my $file_is_ok = 0; 
open FH, ">file.txt" and $file_is_ok = 1; 
warn "No logging available" unless $file_is_ok; 

Тогда везде, где вы хотите использовать дескриптор файла, вы можете проверить первое, что это нормально:

$file_is_ok and print FH "Something happened"; 

Обычно вам нужно немного больше абстракции, чем выше, но я надеюсь, что этого достаточно, чтобы начать.

5

Нет, die определенно не обязательно использовать, иначе провалившийся open просто выйдет из программы. Это просто используемая конструкция, так как часто, если вы не можете открыть файл, нет смысла продолжать, но на самом деле нет требования к die или сделать что-нибудь еще.

1

я мог бы сделать что-то вроде:

sub process_file { 
    my $file = shift; 
    open(my $fh, ">", $file) or return; 
    # write to file ... 
} 
0

Рекомендуется использовать croak() из Carp вместо этого, особенно в модулях или объектов. См. http://perldoc.perl.org/Carp.html

Carp является стандартным модулем и, как и все стандартные модули, устанавливается с Perl. Список всех стандартных модулей доступен в perlmodlib. См http://perldoc.perl.org/perlmodlib.html

0

Если то, что вы пытаетесь сделать, это избежать выхода из программы при возникновении ошибки открытия файла, опуская die не правильный подход. die - механизм исключения Perl; тот факт, что он прерывает программу по умолчанию, является случайным, а не фундаментальным, свойством. Если вы предоставляете обработчик исключений, вы сохраняете контроль. Правильный подход заключается в том, чтобы поймать исключение и выполнить очистку в блоке finally.

use 5.10.0; 
use Try::Tiny; 

my ($infile, $FH); 
try { 
    open $infile, '<', 'infile.txt' or die "Can't open infile"; 
    try { 
     open $FH, '>', 'file.txt' or die "Can't open outfile"; 
     my $line = <$infile>; 
     print $FH $line; 
     say 'Cleaning up $FH'; 
     close $FH; 
    } finally { 
     say 'Cleaning up $infile'; 
     close $infile; 
    } catch { 
     die $_; 
    }; 
} catch { 
    die $_; 
}; 

Так что если open $infile ... терпит неудачу, die к catch блок, который redies и ликвидирует сценарий. Но как только мы открыли $infile, если open $FH терпит неудачу, умрите в блок catch, который также прерывает программу, но сначала произойдет close $infile. Файловые дескрипторы - не лучшие примеры ресурсов для очистки до выхода программы, потому что интерпретатор автоматически закрывает файлы, но основная идея есть.

Если вам не нравятся вложенные блоки try, вы можете добиться такого же эффекта, проверив, какое исключение вызвало блокировку блока и решение о том, какая очистка необходима на основе этого. Это немного более хрупкий, но еще более надежный, чем все, что упоминается goto.

1

К сожалению для ответа на несколько месяцев старый вопрос, но так, как я делаю это за счет реализации моей собственной подпрограммой die стиль:

sub fail { 
    my $text = $_[0]; 

    # Do error-related stuff here, like send an email 
    die($text) # or just exit 
} 

open(my $fh, ">file.txt") or fail("Unable to open file: $!");