Python和Matlab之间的共享文件访问

时间:2015-03-16 19:24:56

标签: python windows matlab file shared

我有一个Matlab应用程序,它写入.csv文件和从中读取的Python脚本。这些操作同时发生并且在它们各自的时期(不一定相同)发生。所有这些都在Windows 7上运行。

我想知道:

  1. 操作系统本身是否会提供某种锁定机制,以便只有两个应用程序中的一个--Matlab或Python - 可以访问共享文件?
  2. 在Python应用程序中,如何检查文件是否已经由Matlab应用程序打开?#34;打开?什么是循环结构,以便Python应用程序被阻止,直到它获得读取文件的访问权限?

3 个答案:

答案 0 :(得分:0)

我不确定window用于锁定文件的API

这是一个可能的解决方案:

  1. 当matlab打开文件时,你会创建一个名为" data.lock"的空文件。或类似的东西。

  2. 当python尝试读取文件时,它将检查锁定文件,如果存在,则它会在给定的时间间隔内休眠。

  3. 当matlab完成文件后,它可以删除" data.lock"文件

  4. 它是一个程序化的解决方案,但它比通过windows api挖掘并在matlab和python中找到正确的调用更简单。

答案 1 :(得分:0)

如果Python只读取文件,我相信你必须将它锁定在MATLAB中,因为Python的只读打开调用可能不会失败。我不知道如何做到这一点,你可能想要阅读这个问题atomically creating a file lock in MATLAB (file mutex)

但是,如果您只是使用python使用数据,您是否考虑使用套接字而不是文件?

答案 2 :(得分:0)

在Python端的Windows中,可以使用特定的共享模式(直接或间接通过CRT)调用CreateFile。例如,如果所需的共享模式为FILE_SHARE_READ,则如果文件已打开以进行写入,则打开将失败。如果后者调用成功,那么将来尝试打开文件进行写入将失败(例如在Matlab中)。

Windows CRT功能_wsopen_s允许设置共享模式。您可以在Python 3 opener中使用ctypes调用它:

import sys
import os
import ctypes as ctypes
import ctypes.util

__all__ = ['shdeny', 'shdeny_write', 'shdeny_read']

_SH_DENYRW = 0x10  # deny read/write mode
_SH_DENYWR = 0x20  # deny write mode
_SH_DENYRD = 0x30  # deny read
_S_IWRITE  = 0x0080  # for O_CREAT, a new file is not readonly

if sys.version_info[:2] < (3,5):
    _wsopen_s = ctypes.CDLL(ctypes.util.find_library('c'))._wsopen_s
else:
    # find_library('c') may be deprecated on Windows in 3.5, if the 
    # universal CRT removes named exports. The following probably 
    # isn't future proof; I don't know how the '-l1-1-0' suffix 
    # should be handled.
    _wsopen_s = ctypes.CDLL('api-ms-win-crt-stdio-l1-1-0')._wsopen_s

_wsopen_s.argtypes = (ctypes.POINTER(ctypes.c_int), # pfh
                      ctypes.c_wchar_p,             # filename
                      ctypes.c_int,                 # oflag
                      ctypes.c_int,                 # shflag
                      ctypes.c_int)                 # pmode

def shdeny(file, flags):
    fh = ctypes.c_int()
    err = _wsopen_s(ctypes.byref(fh),
                    file, flags, _SH_DENYRW, _S_IWRITE)
    if err:
        raise IOError(err, os.strerror(err), file)
    return fh.value

def shdeny_write(file, flags):
    fh = ctypes.c_int()
    err = _wsopen_s(ctypes.byref(fh),
                    file, flags, _SH_DENYWR, _S_IWRITE)
    if err:
        raise IOError(err, os.strerror(err), file)
    return fh.value

def shdeny_read(file, flags):
    fh = ctypes.c_int()
    err = _wsopen_s(ctypes.byref(fh),
                    file, flags, _SH_DENYRD, _S_IWRITE)
    if err:
        raise IOError(err, os.strerror(err), file)
    return fh.value

例如:

if __name__ == '__main__':
    import tempfile
    filename = tempfile.mktemp()
    fw = open(filename, 'w')
    fw.write('spam')
    fw.flush()
    fr = open(filename)
    assert fr.read() == 'spam'
    try:
        f = open(filename, opener=shdeny_write)
    except PermissionError:
        fw.close()
        with open(filename, opener=shdeny_write) as f:
            assert f.read() == 'spam'
    try:
        f = open(filename, opener=shdeny_read)
    except PermissionError:
        fr.close()
        with open(filename, opener=shdeny_read) as f:
            assert f.read() == 'spam'
    with open(filename, opener=shdeny) as f:
        assert f.read() == 'spam'
    os.remove(filename)

在Python 2中,您必须将上述开场白与os.fdopen结合起来,例如:

f = os.fdopen(shdeny_write(filename, os.O_RDONLY|os.O_TEXT), 'r')

或者定义一个sopen包装器,它允许您显式传递共享模式并调用os.fdopen以返回Python 2 file。这需要更多的工作来从传入的mode中获取文件flags,反之亦然。