Менеджеры контекста в Matlab: вызов __enter__ в Matlab

У меня есть пакет Python, и я хотел бы использовать его классы и методы в Matlab. Я знаю, что это можно сделать напрямую, начиная с Matlab 2014b. Я имею в виду, что все, что вам нужно сделать, это добавить py. в начале ваших утверждений. Пока все хорошо, однако я не мог понять, как работать с менеджерами контекста через MATLAB, которые вызываются с помощью оператора with. Например, предположим, что у нас есть следующий класс в модуле с именем app.py:

class App(object):

    def __init__(self, input):
        self._input = input
        self._is_open = False

    def __enter__(self):
        self._is_open = True
        # many other stuff going after this but not relevant to this problem

В Matlab я могу назвать это как

app = py.app.App(input);
py.getattr(app, '_is_open')

ans =

logical

0

и я вижу экземпляр приложения в своей рабочей области. Однако, как и ожидалось, таким образом вызывается только __init__, но не __enter__.

Итак, есть ли способ вызвать __enter__ из Matlab, как если бы мы вызывали его как with App(input) as app: в Python?

Примечание. Я использую Python 3.5.1 и Matlab 2017b.


person hko    schedule 09.11.2017    source источник


Ответы (1)


Я не верю, что есть какой-либо способ вызвать метод __enter__ класса Python из MATLAB, но метод __exit__ может вызываться неявно (об этом я расскажу ниже).

Важно сначала рассмотреть назначение менеджеров контекста (через __enter__ и __exit__ методы), который должен предоставить способ выделения и высвобождения ресурсов в режиме, ограниченном областью действия, вне зависимости от того, происходит ли выход из этой области обычным образом или из-за ошибки. MATLAB имеет более ограниченные средства «обзора»: каждая функция имеет свою собственную workspace, а управляющие структуры, такие как циклы, условные операторы и т. д. внутри этой функции, совместно используют это рабочее пространство (в отличие от многих языков, в которых эти управляющие структуры имеют свои собственные подобласти).

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

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

  s = fread(fid);
  ...
end

Здесь файл открывается и затем считывается. Создается onCleanup объект c, который закроет файл, когда c будет очищено из памяти при выходе из функции. Если бы файл был просто закрыт с помощью fclose(fid) в конце функции, то выход из функции по ошибке (например, во время чтения данных) привел бы к тому, что файл все еще оставался бы открытым. Использование объекта onCleanup гарантирует, что файл будет закрыт независимо от выхода из функции. Вот пример того, как это может быть обработано в Python:

with open('some_file', 'w') as opened_file:
    opened_file.write('Hola!')

Поскольку MATLAB имеет другие средства «управления контекстом», чем Python, это может объяснить, почему невозможно получить доступ к методу __enter__. Я попробовал с классом, который, как я знал, был: io.FileIO учебный класс. Сначала я искал помощи:

>> py.help('io.FileIO.__enter__')
Help on method_descriptor in io.FileIO:

io.FileIO.__enter__ = __enter__(...)

Он находит текст справки. Это не особенно полезно, но оно есть. Однако, когда я создаю объект и просматриваю его список методов, ни __enter__, ни __exit__ (и явного эквивалента) там нет:

>> fio = py.io.FileIO('test.txt');
>> methods(fio)

Methods for class py._io.FileIO:

FileIO      eq          ge          le          read        readinto    seek        truncate    writelines  
char        fileno      gt          lt          readable    readline    seekable    writable    
close       flush       isatty      ne          readall     readlines   tell        write       

Methods of py._io.FileIO inherited from handle.

Methods for class handle:

addlistener  eq           findprop     gt           le           ne           
delete       findobj      ge           isvalid      lt           notify

Однако я заметил кое-что интересное, когда очистил объект fio. Пока объект fio все еще существовал (с открытым файлом), я не мог удалить или переместить файл, как и ожидалось. Однако после ввода команды clear fio, без предварительного закрытия файла, я смог нормально взаимодействовать с файлом. Это означает, что файл был автоматически закрыт. Это заставляет меня задаться вопросом, может ли метод __exit__ вызываться неявно, но мне еще предстоит определить это наверняка.

person gnovice    schedule 11.11.2017