Очистка после завершения выполнения функции

Обзор

Хорошая методика программирования должна убедиться, что вы оставляете свою среду программы в чистом состоянии, которое не вмешивается ни в какой другой код программы. Например, вы можете хотеть

  • Закройте любые файлы, которые вы открыли для импорта или экспорта.

  • Восстановите путь MATLAB®.

  • Заблокируйте или разблокируйте память, чтобы предотвратить или позволить стирать функцию MATLAB или файлы MEX.

  • Задержите свою рабочую папку к ее значению по умолчанию, если вы изменили ее.

  • Убедитесь, что глобальные и персистентные переменные находятся в правильном состоянии.

MATLAB обеспечивает функцию onCleanup с этой целью. Эта функция, когда используется в рамках любой программы, устанавливает стандартную программу очистки для этой функции. Когда функция отключает, или обычно или в случае ошибки или Ctrl+C, MATLAB автоматически выполняет стандартную программу очистки.

Следующий оператор устанавливает стандартную программу очистки cleanupFun для в настоящее время под управлением программы:

cleanupObj = onCleanup(@cleanupFun);

Когда ваша программа выходит, MATLAB находит любые экземпляры класса onCleanup и выполняет указатели присоединенной функции. Процесс очистки функции генерации и активации включает следующие шаги:

  1. Запишите одну или несколько стандартных программ очистки для разрабатываемой программы. Примите на данный момент, что требуется только одна такая стандартная программа.

  2. Создайте указатель на функцию для стандартной программы очистки.

  3. В какой-то момент, обычно рано в вашем коде программы, вставьте вызов функции oncleanup, передав указатель на функцию.

  4. Когда программа запущена, вызов onCleanup создает объект очистки, который содержит указатель на стандартную программу очистки, созданную на шаге 1.

  5. Когда программа заканчивается, MATLAB неявно очищает все объекты, которые являются локальными переменными. Это вызывает метод деструктора для каждого локального объекта в вашей программе, включая объект очистки, созданный на шаге 4.

  6. Метод деструктора для этого объекта вызывает эту стандартную программу, если это существует. Это выполняет задачи, должен был восстановить вашу среду программирования.

Можно объявить любое количество стандартных программ очистки для программного файла. Каждый вызов onCleanup устанавливает отдельную стандартную программу очистки для каждого возвращенного объекта очистки.

Если по некоторым причинам объект, возвращенный onCleanup, сохраняется вне срока действия вашей программы, то стандартная программа очистки, сопоставленная с тем объектом, не запущена, когда ваша функция отключает. Вместо этого это запустится каждый раз, когда объект уничтожается (e. g., путем очистки переменной объекта).

Ваша стандартная программа очистки никогда не должна полагаться на переменные, которые заданы за пределами той стандартной программы. Например, вложенная функция, показанная здесь слева, выполняется без ошибки, тогда как очень похожий на праве перестал работать с ошибкой, Undefined function or variable 'k'. Это следует из уверенности стандартной программы очистки в переменном k, который задан за пределами вложенной стандартной программы очистки:

function testCleanup               function testCleanup
k = 3;                             k = 3;
myFun                              obj = onCleanup(@myFun);
    function myFun                     function myFun
    fprintf('k is %d\n', k)            fprintf('k is %d\n', k)
    end                                end
end                                end

Примеры очистки программы на выход

Пример 1 - закрывает открытые файлы на выходе

MATLAB закрывает файл с идентификатором fid, когда функциональный openFileSafely отключает:

function openFileSafely(fileName)
fid = fopen(fileName, 'r');
c = onCleanup(@()fclose(fid));

s = fread(fid);
     .
     .
     .
end

Пример 2 - поддерживает выбранную папку

Этот пример сохраняет текущую папку, возвращает ли functionThatMayError ошибку или нет:

function changeFolderSafely(fileName)
   currentFolder = pwd;
   c = onCleanup(@()cd(currentFolder));

   functionThatMayError;
   end   % c executes cd(currentFolder) here.

Пример 3 - закрывает фигуру и восстанавливает путь MATLAB

Этот пример расширяет путь MATLAB, чтобы включать файлы в toolbox\images папки, и затем отображает фигуру от одной из этих папок. После того, как фигура отображается, стандартная программа очистки, restore_env закрывает фигуру и восстанавливает путь к его исходному состоянию.

function showImageOutsidePath(imageFile)
fig1 = figure;
imgpath = genpath([matlabroot '\toolbox\images']);

% Define the cleanup routine.
cleanupObj = onCleanup(@()restore_env(fig1, imgpath));

% Modify the path to gain access to the image file, 
% and display the image.
addpath(imgpath);
rgb = imread(imageFile);
fprintf('\n   Opening the figure %s\n', imageFile);
image(rgb);
pause(2);

   % This is the cleanup routine.
   function restore_env(fighandle, newpath)
   disp '   Closing the figure'
   close(fighandle);
   pause(2)
   
   disp '   Restoring the path'
   rmpath(newpath);
   end
end

Запустите функцию как показано сюда. Можно проверить, что путь был восстановлен путем сравнения длины пути до и после выполнения функции:

origLen = length(path);

showImageOutsidePath('greens.jpg')
   Opening the figure greens.jpg
   Closing the figure
   Restoring the path

currLen = length(path);
currLen == origLen
ans =
     1

Получение информации о стандартной программе очистки

В Примере 3 показанных выше, стандартная программа очистки и данные должны были вызвать его, содержатся в указателе на анонимную функцию:

@()restore_env(fig1, imgpath)

Детали того указателя затем содержатся в объекте, возвращенном функцией onCleanup:

cleanupObj = onCleanup(@()restore_env(fig1, imgpath));

Можно получить доступ к этим деталям с помощью свойства task объекта очистки как показано здесь. (Измените функцию showImageOutsidePath путем добавления следующего кода незадолго до строки с комментариями, которая говорит, “% This is the cleanup routine.”),

disp '   Displaying information from the function handle:'
task = cleanupObj.task;
fun = functions(task)
wsp = fun.workspace{2,1}
fprintf('\n');
pause(2);

Запустите измененную функцию, чтобы видеть вывод команды functions и содержимое одной из ячеек workspace:

showImageOutsidePath('greens.jpg')

Opening the figure greens.jpg
Displaying information from the function handle:
fun = 
     function: '@()restore_env(fig1,imgpath)'
         type: 'anonymous'
         file: 'c:\work\g6.m'
    workspace: {2x1 cell}
wsp = 
     imageFile: 'greens.jpg'
          fig1: 1
       imgpath: [1x3957 char]
    cleanupObj: [1x1 onCleanup]
           rgb: [300x500x3 uint8]
          task: @()restore_env(fig1,imgpath)

Closing the figure
Restoring the path

Используя onCleanup По сравнению с попыткой/выгодой

Другой способ запустить стандартную программу очистки, когда функция отключает неожиданно, состоит в том, чтобы использовать оператор try, catch. Существуют ограничения к использованию этого метода как бы то ни было. Если стороны пользователя программа путем ввода Ctrl+C, MATLAB сразу выходит из блока try, и стандартная программа очистки никогда не выполняется. Стандартная программа очистки также не запускается, когда вы обычно выходите из функции.

Следующая программа очищает, если ошибка происходит, но не в ответ на Ctrl+C:

function cleanupByCatch
try
    pause(10);
catch
    disp('   Collecting information about the error')
    disp('   Executing cleanup tasks')
end

В отличие от оператора try/catch, функция onCleanup не только отвечает на нормальный выход из вашей программы и любой ошибки, которая может быть выдана, но также и к Ctrl+C. Этот следующий пример заменяет try/catch на onCleanup:

function cleanupByFunc
obj = onCleanup(@()...
    disp('   Executing cleanup tasks'));
pause(10);

onCleanup в Скриптах

onCleanup не работает в скриптах, как он делает в функциях. В функциях объект очистки хранится в функциональной рабочей области. Когда функция выходит, эта рабочая область очищена, таким образом выполнив связанную стандартную программу очистки. В скриптах объект очистки хранится в базовом рабочем пространстве (то есть, рабочая область, используемая в интерактивной работе, сделанной в командной строке). Поскольку выход из скрипта не имеет никакого эффекта на базовое рабочее пространство, объект очистки не очищен, и стандартная программа, сопоставленная с тем объектом, не выполняется. Чтобы использовать этот тип механизма очистки в скрипте, необходимо было бы явным образом очистить объект от командной строки или другого скрипта, когда первый скрипт отключает.

Была ли эта тема полезной?