Обеспечивает ли запись файла на диск с помощью Python open (). Write () доступность данных для других процессов? - PullRequest
8 голосов
/ 31 октября 2011

Один процесс Python записывает обновления состояния в файл для чтения другими процессами.В некоторых случаях обновления статуса происходят многократно и быстро в цикле.Самый простой и быстрый подход - использовать open (). Write () в одну строку:

open(statusfile,'w').write(status) 

Альтернативный подход с четырьмя строками, которые переносят данные на диск.Это значительно снижает производительность:

f = open(self.statusfile,'w')

f.write(status)

os.fsync(f)

f.close()

Я не пытаюсь защититься от сбоя ОС.Итак, принуждает ли этот подход данные в буфер ОС, чтобы другие процессы считывали новейшие данные о состоянии, когда открывали файл с диска?Или мне нужно использовать os.fsync ()?

Ответы [ 2 ]

12 голосов
/ 31 октября 2011

Нет, первый подход не гарантирует записи данных, поскольку не гарантируется, что файл будет сброшен и закрыт, когда на дескриптор больше не ссылается его член write.Это, вероятно, имеет место с CPython, но не обязательно с другими интерпретаторами Python;это деталь реализации сборщика мусора Python.

Вы действительно должны использовать второй подход, за исключением того, что os.fsync не требуется;просто закройте файл, и данные должны быть доступны другим процессам.

Или, что еще лучше ( Python> = 2.5 ):

with open(self.statusfile, 'w') as f:
    f.write(status)

withверсия безопасна для исключений: файл закрывается даже в случае сбоя write.

0 голосов
/ 31 октября 2011

Начиная с Python 2.2 стало возможным создавать подклассы встроенных типов языка. Это означает, что вы можете получить свой собственный тип file, чей метод write() вернул self вместо того, что делает встроенная версия. Это позволило бы также связать вызов метода close() с концом вашей строки.

class ChainableFile(file):
    def __init__(self, *args, **kwargs):
        return file.__init__(self, *args, **kwargs)

    def write(self, str):
        file.write(self, str)
        return self

def OpenFile(filename, *args, **kwargs):
    return ChainableFile(filename, *args, **kwargs)

statusfile = 'statusfile.txt'
status = 'OK\n'

OpenFile(statusfile,'w').write(status).close()
...