2015-03-16 3 views
2

У меня есть приложение Matlab, которое записывает в .csv-файл и скрипт Python, который читает с него. Эти операции происходят одновременно и в соответствующие периоды (не обязательно одинаковые). Все это работает на Windows 7.Общий доступ к файлам между Python и Matlab

Я хотел бы знать:

  1. ли операционная система по своей сути обеспечивает какое-то механизм блокировки, так что только один из двух приложений - Matlab или Python - иметь доступ к общий файл?
  2. В приложении Python, как проверить, что файл уже открыт для приложения Matlab? Какова структура цикла для этого, чтобы приложение Python блокировалось до получения доступа к чтению файла?
+0

Если файл открыт на окнах, вы не получите сообщение об ошибке? –

+0

Ну, это на самом деле только один возможный случай использования. Позже у меня может быть и другое, а то, как пишет Python, в то время как Matlab читает. Так будет ли работать метод _winapi.CreateFile в таком сценарии? – JDD

ответ

0

Я не уверен, что API окна для блокирующих файлов

Heres возможное решение:

  1. Хотя MATLAB имеет открытый файл, необходимо создать пустой файл с именем «data.lock» Или что-то в этом роде.

  2. Когда python пытается прочитать файл, он проверяет файл блокировки, и если он есть, то он будет спать в течение заданного интервала.

  3. Когда файл matlab завершен с файлом, он может удалить файл data.lock.

Ее программным решением, но это проще, чем копаться в Windows API, и найти правильные звонки в MATLAB и питона.

+0

Что касается проверки того, открыт ли файл уже, было бы проще просто попытаться открыть его и поймать ошибку. –

+0

Несомненно, это один из способов сделать то, что я могу управлять доступом к файлу, используя «data.lock» в качестве объекта блокировки. Я ищу решения, которые используют встроенные методы Python и Matlab для обработки этого. – JDD

+0

Я очень хорошо знаком с python, и вы не найдете встроенный метод для этой конкретной задачи в python без использования внешней библиотеки. Вот внешний lib [связанный вопрос] (http://stackoverflow.com/questions/489861/locking-a-file-in-python). Надеюсь это поможет. –

0

Если Python только читает файл, я считаю, что вам нужно заблокировать его в MATLAB, потому что открытый вызов Python для чтения может не работать. Я не уверен, как это сделать, вы можете прочитать этот вопрос. atomically creating a file lock in MATLAB (file mutex)

Однако, если вы просто потребляете данные с помощью python, считаете ли вы использование сокета вместо файла?

0

В Windows со стороны Python CreateFile можно вызвать (прямо или косвенно через ЭЛТ) в определенном режиме совместного доступа. Например, если желаемый режим совместного доступа равен FILE_SHARE_READ, тогда сбой будет открыт, если файл уже открыт для записи. Если последний вызов вместо этого преуспевает, то неудачная попытка открыть файл для записи завершится неудачно (например, в Matlab).

Функция Windows CRT _wsopen_s позволяет установить режим совместного доступа. Вы можете назвать это с ctypes в 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, чтобы вернуть Python 2 file.Для этого потребуется немного больше работы, чтобы получить файл mode из полученного в flags или наоборот.

+0

Спасибо за все ваши усилия, но я нашел другое решение более простым! – JDD

+0

Да, другое решение проще, поскольку вы беспокоитесь только о контроле доступа между Matlab и вашим скриптом Python. Настройка режима совместного использования ОС - универсальное решение. – eryksun

Смежные вопросы