Как проверить, открыт ли уже файл (в том же процессе)

И я хотел бы добиться этого с помощью конструкции try catch.

Этот связанный вопрос предполагает, что я могу сделать:

try:
    open(fileName, 'wb+')
except:
    print("File already opened!")
    raise

Однако у меня это не работает. Я могу открыть один и тот же файл несколько раз без каких-либо проблем:

fileObj1 = open(fileName, 'wb+')
fileObj2 = open(fileName, 'wb+')

Это потому, что у меня Python 3.5? Или потому что я использую Raspbian?

Спасибо за помощь!


person maximedupre    schedule 29.05.2016    source источник
comment
Причина, по которой я могу открывать файл несколько раз, заключается в том, что только Windows блокирует файлы при открытии для записи. Платформы POSIX этого не делают. См. stackoverflow.com/questions/22617452/ для получения дополнительной информации.   -  person maximedupre    schedule 30.05.2016
comment
Если вы работаете в том же процессе, как вы не узнаете, открыт ли файл?   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham У меня есть скрипт, который импортирует внешнюю библиотеку/модуль, который может открывать и закрывать файл. Моему сценарию нужен способ узнать, открыт ли файл в данный момент или закрыт.   -  person maximedupre    schedule 30.05.2016
comment
Так вы на самом деле не открываете файл с помощью wb+? Это означает чтение записи, но сначала она усекает данные, вы будете читать их только после того, как что-то написали, и искать обратно.   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham Что ты имеешь в виду? На самом деле мне не нужно открывать файл в моем сценарии. В моем вопросе я делаю это, потому что ожидал, что он выдаст ошибку, если файл уже открыт, что позволит мне проверить, открыт или закрыт файл.   -  person maximedupre    schedule 30.05.2016
comment
Я думаю, что у вас может быть проблема с xy, если вы добавите контекст к своему вопросу, это может помочь получить лучший ответ.   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham Честно говоря, я думаю, что это довольно ясно. Два ответа ниже конкретно касаются проблемы. Я пытаюсь проверить, открыт ли уже файл. Мой вопрос показывает, что я пробовал; open файл, который я хочу проверить, открыт или нет, и ожидаю ошибку, если файл уже был открыт. К сожалению, это не работает, потому что моя ОС является платформой POSIX. Мне не нужно открывать файл, это всего лишь один из способов проверить, открыт файл или нет.   -  person maximedupre    schedule 30.05.2016
comment
Что произойдет, если файл уже открыт?   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham Вы имеете в виду, если я попытаюсь открыть файл, который уже открыт? Ничего, я просто получаю несколько файловых объектов. Как указано в моем вопросе, я могу без проблем открывать один и тот же файл несколько раз.   -  person maximedupre    schedule 30.05.2016
comment
Я имею в виду в вашем коде, как знание того, открыт файл или нет, влияет на поток вашего кода?   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham Мне нужно переместить файл с помощью shutil.move, но я не хочу этого делать, если он в данный момент записывается/если он открыт.   -  person maximedupre    schedule 30.05.2016
comment
Но это вообще не проблема в Linux, индексный узел никогда не перемещается, меняются только записи каталога, предполагая, что вы находитесь в одной и той же файловой системе? unix.stackexchange.com/questions/164577/ stackoverflow.com/questions/11818802/   -  person Padraic Cunningham    schedule 30.05.2016
comment
@PadraicCunningham Ну, это проблема, потому что для того, чтобы продолжать писать в этот файл после его перемещения, вам нужен новый файловый объект. Любая внешняя библиотека не знает, был ли перемещен файл или нет, поэтому она не знает, что должна создать другой файловый объект с новым местоположением.   -  person maximedupre    schedule 30.05.2016


Ответы (2)


Вы должны открыть один и тот же файл, но присвоить его разным переменным, например:

file_obj = open(filename, "wb+")

if not file_obj.closed:
    print("File is already opened")

.closed только проверяет, был ли файл открыт тем же процессом Python.

person atakanyenel    schedule 29.05.2016
comment
Это не решает вопрос ОП? Он спрашивает, как проверить, открыт ли конкретный файл. f=open(f_name, mode) != f_o=open(f_name, mode), потому что open() возвращает экземпляр некоторого файлового объекта. Следовательно, fileobj.closed всегда будет оцениваться как False, если вы открыли файл в предыдущей строке? - person TheLazyScripter; 30.05.2016
comment
Хотя этот метод менее гибкий и не использует конструкцию try...except, он не зависит от платформы и действительно работает. Я не знаю, почему за это проголосовали. - person maximedupre; 30.05.2016
comment
@maximedupre Я не минусовал, но подозреваю, что это потому, что большинство людей попадают сюда, потому что они пытаются выяснить, открыт ли файл в другом процессе, а это гораздо больше. трудная проблема. Но, как указано в вашей теме, это для того же процесса, поэтому этот ответ на 100% правильный и не должен быть занижен, он просто бесполезен для большинства людей ;-) - person JohnE; 30.07.2018

Я бы предложил использовать что-то вроде этого

# Only works on Windows
def is_open(file_name):
    if os.path.exists(file_name):
        try:
            os.rename(file_name, file_name) #can't rename an open file so an error will be thrown
            return False
        except:
            return True
    raise NameError

Отредактировано, чтобы соответствовать конкретным проблемам ОП.

class FileObject(object):
    def __init__(self, file_name):
        self.file_name = file_name
        self.__file = None
        self.__locked = False

    @property
    def file(self):
        return self.__file

    @property
    def locked(self):
        return self.__locked

    def open(self, mode, lock=True):#any testing on file should go before the if statement such as os.path.exists()
        #replace mode with *args if you want to pass multiple modes
        if not self.locked:
            self.__locked = lock
            self.__file = open(self.file_name, mode)
            return self.file
        else:
            print 'Cannot open file because it has an exclusive lock placed on it'
            return None #do whatever you want to do if the file is already open here

    def close(self):
        if self.file != None:
            self.__file.close()
            self.__file = None
            self.__locked = False

    def unlock(self):
        if self.file != None:
            self.__locked = False
person TheLazyScripter    schedule 29.05.2016
comment
Это не работает, я могу rename открыть файл, даже если он открыт. Возможно, потому что моя ОС Raspbian? - person maximedupre; 30.05.2016
comment
Возможно, эта блокировка специфична для ОС, если это так, то я бы взглянул на режимы открытия Python здесь tutorialspoint .com/python/os_open.htm и попробуйте os.O_CREAT, а также os.O_EXLOCK или их комбинацию. Дайте мне знать, если это работает на Raspbian. Я предполагаю, что это будет, потому что это не специфично для ОС. - person TheLazyScripter; 30.05.2016
comment
os.O_EXLOCK не будет доступен на пи - person Padraic Cunningham; 30.05.2016
comment
Да, os.O_EXLOCK недоступен на Pi. Когда я пробую это, я получаю AttributeError: module 'os' has no attribute 'O_EXLOCK'. - person maximedupre; 30.05.2016
comment
Из документа Python 3.5: Следующие константы являются опциями параметра flags для функция open(). Их можно комбинировать с помощью побитового оператора ИЛИ |. Некоторые из них доступны не на всех платформах. - person maximedupre; 30.05.2016
comment
тогда я бы создал и поделился вашим собственным файлом obj. Ищите мой обновленный ответ. - person TheLazyScripter; 30.05.2016
comment
Ах да, спасибо за этот отличный пользовательский класс файловых объектов. Это определенно работает, когда вы единственный, кто касается и поддерживает файл, но в контексте, когда в игре есть сторонние библиотеки/модули, это сложнее. Например, я не могу сказать библиотеке, которая создает файл, который я хочу проверить, открыт или не использовать этот пользовательский класс объектов файла. Я уверен, что другие найдут это полезным. - person maximedupre; 30.05.2016