как запустить кусок кода перед выходом из Perl-скрипта - PullRequest
10 голосов
/ 20 июня 2010

В моем скрипте мне нужно загрузить некоторую информацию из файла на диске, и во время выполнения скрипта информация может быть изменена. Чтобы сохранить постоянство файла на диске, и он находится в копии памяти, мне нужно записать информацию обратно вдиск всякий раз, когда информация изменяется в памяти, или периодически записывать их обратно на диск, или просто записывать их обратно во время выхода из скрипта, что является предпочтительным, потому что это сэкономит много времени ввода-вывода и сделает скрипт отзывчивым.

Так что, как и заголовок, у меня вопрос: есть ли в perl какой-то механизм, который удовлетворит мои потребности?

Ответы [ 2 ]

28 голосов
/ 20 июня 2010

Я думаю, что вы ищете END блок :

END {
    # cleanup
}

Блок кода END выполняется как можно позже, то есть после того, как perl завершил выполнение программы и непосредственно перед выходом из интерпретатора, даже если он завершается в результате выполнения функции die (). (Но не в том случае, если он превращается в другую программу через exec или вылетает из воды по сигналу - вы должны поймать его в ловушку самостоятельно (если можете).) У вас может быть несколько блоков END в файле - они будут выполнить в обратном порядке определения; то есть: последний вошел, первый вышел (LIFO). Блоки END не выполняются при запуске perl с ключом -c или при сбое компиляции.

9 голосов
/ 20 июня 2010

Есть два разных способа сделать это, в зависимости от того, что вы ищете.

  • Блок END выполняется, когда переводчик выключен. Смотрите предыдущий ответ для более подробной информации:)
  • Блок / суб DESTROY, который выполняется, когда ваш объект выходит из области видимости. То есть, если вы хотите встроить свою логику в модуль или класс, вы можете использовать DESTROY.

Взгляните на следующий пример (это рабочий пример, но некоторые детали, такие как проверка ошибок и т. Д. Опущены):

#!/usr/bin/env perl

package File::Persistent;

use strict;
use warnings;
use File::Slurp;

sub new {
    my ($class, $opt) = @_;

    $opt ||= {};

    my $filename = $opt->{filename} || "./tmpfile";
    my $self = {
        _filename => $filename,
        _content => "",
    };

    # Read in existing content
    if (-s $filename) {
        $self->{_content} = File::Slurp::read_file($filename);
    }

    bless $self, $class;
}

sub filename {
    my ($self) = @_;
    return $self->{_filename};
}

sub write {
    my ($self, @lines) = @_;
    $self->{_content} .= join("\n", @lines);
    return;
}

sub DESTROY {
    my ($self) = @_;
    open my $file_handle, '>', $self->filename
        or die "Couldn't save persistent storage: $!";
    print $file_handle $self->{_content};
    close $file_handle;
}

# Your script starts here...
package main;

my $file = File::Persistent->new();

$file->write("Some content\n");

# Time passes...
$file->write("Something else\n");

# Time passes...
$file->write("I should be done now\n");

# File will be written to only here..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...