【问题标题】:Context Managers in Matlab: Invoking __enter__ in MatlabMatlab 中的上下文管理器:在 Matlab 中调用 __enter__
【发布时间】:2018-04-21 21:21:54
【问题描述】:

我有一个 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

我在我的工作区中看到了一个 App 实例。然而,正如预期的那样,只有__init__ 被这样调用,而不是__enter__

那么,有没有办法从 Matlab 中调用 __enter__,就好像我们在 Python 中调用 with App(input) as app: 一样?

注意:我使用的是 Python 3.5.1 和 Matlab 2017b

【问题讨论】:

    标签: python matlab exit enter contextmanager


    【解决方案1】:

    我不相信有任何方法可以从 MATLAB 调用 Python 类的 __enter__ 方法,但 __exit__ 方法可能会被隐式调用(我将进一步解决这个问题下面)。

    首先考虑context managers 的目的很重要(通过__enter____exit__ 方法),即提供一种以有限范围的方式分配和释放资源的方法,无论该范围与否正常退出或通过错误退出。 MATLAB 的“作用域”方式更为有限:每个函数都有自己的workspace,并且该函数内的循环、条件语句等控制结构都共享该工作区(与许多语言不同,这些控制结构有自己的子范围)。

    当在 MATLAB 中退出工作区时,其中包含的变量会被清除,但任何已分配的资源可能仍需要释放。这可以通过onCleanup 对象来实现。当它们从内存中清除时,它们会调用一个给定的函数来管理现有资源。 example 将打开并读取文件:

    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__(...)
    

    它会找到一些帮助文本。它不是特别有帮助,但它就在那里。但是,当我创建一个对象并查看它的 methods list 时,__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__ 方法是否会被隐式调用,但我还没有确定它。

    【讨论】:

      猜你喜欢
      • 2018-05-22
      • 2017-01-29
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多