Python 和 Matlab 之间的共享文件访问
Shared file access between Python and Matlab
我有一个写入 .csv 文件的 Matlab 应用程序和一个从中读取的 Python 脚本。这些操作同时发生并在各自的周期内发生(不一定相同)。所有这些都在 Windows 7.
上运行
我想知道:
- OS 是否会固有地提供某种锁定机制,以便两个应用程序中只有一个 - Matlab 或 Python - 可以访问共享文件?
- 在 Python 应用程序中,如何检查文件是否已被 Matlab 应用程序 "open" 编辑?这是什么循环结构,以便 Python 应用程序在获得读取文件的权限之前被阻止?
我不确定 window 的 API 用于锁定文件
这是一个可能的解决方案:
虽然 matlab 打开了文件,但您创建了一个名为 "data.lock" 或类似名称的空文件。
当python 尝试读取文件时,它将检查锁定文件,如果存在,那么它将休眠一段给定的时间间隔。
当matlab处理完文件后,它可以删除"data.lock"文件。
它是一个编程解决方案,但它比挖掘 windows api 并在 matlab 和 python.
中找到正确的调用要简单
如果 Python 只是读取文件,我相信您必须在 MATLAB 中锁定它,因为来自 Python 的只读打开调用可能不会失败。我不确定如何做到这一点,你可能想阅读这个问题 atomically creating a file lock in MATLAB (file mutex)
但是,如果您只是使用 python 消费数据,您是否考虑过使用套接字而不是文件?
在Python端的Windows中,CreateFile
可以通过特定的共享模式调用(直接或间接通过CRT)。例如,如果所需的共享模式是 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
到 return a Python 2 file
。这将需要更多工作才能从传入的 flags
中获取文件 mode
,反之亦然。
我有一个写入 .csv 文件的 Matlab 应用程序和一个从中读取的 Python 脚本。这些操作同时发生并在各自的周期内发生(不一定相同)。所有这些都在 Windows 7.
上运行我想知道:
- OS 是否会固有地提供某种锁定机制,以便两个应用程序中只有一个 - Matlab 或 Python - 可以访问共享文件?
- 在 Python 应用程序中,如何检查文件是否已被 Matlab 应用程序 "open" 编辑?这是什么循环结构,以便 Python 应用程序在获得读取文件的权限之前被阻止?
我不确定 window 的 API 用于锁定文件
这是一个可能的解决方案:
虽然 matlab 打开了文件,但您创建了一个名为 "data.lock" 或类似名称的空文件。
当python 尝试读取文件时,它将检查锁定文件,如果存在,那么它将休眠一段给定的时间间隔。
当matlab处理完文件后,它可以删除"data.lock"文件。
它是一个编程解决方案,但它比挖掘 windows api 并在 matlab 和 python.
中找到正确的调用要简单如果 Python 只是读取文件,我相信您必须在 MATLAB 中锁定它,因为来自 Python 的只读打开调用可能不会失败。我不确定如何做到这一点,你可能想阅读这个问题 atomically creating a file lock in MATLAB (file mutex)
但是,如果您只是使用 python 消费数据,您是否考虑过使用套接字而不是文件?
在Python端的Windows中,CreateFile
可以通过特定的共享模式调用(直接或间接通过CRT)。例如,如果所需的共享模式是 FILE_SHARE_READ
,那么如果文件已经打开用于写入,则打开将失败。如果后一个调用成功,则以后打开文件进行写入的尝试将失败(例如在 Matlab 中)。
Windows CRT函数_wsopen_s
允许设置共享模式。您可以在 Python 3 opener
:
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
到 return a Python 2 file
。这将需要更多工作才能从传入的 flags
中获取文件 mode
,反之亦然。