Подтвердить что ты не робот

Почему мой файл закрывается, если я ничего не сделаю с ним некоторое время?

Исходная ситуация:

Приложение, над которым я сейчас работаю, получит уведомление от другого приложения, когда определенный файл добавил данные и готов к чтению. На данный момент у меня есть что-то вроде этого:

class Foo(object):
    def __init__(self):
        self.myFile = open("data.txt", "r")
        self.myFile.seek(0, 2) #seeks to the end of the file

        self.mainWindow = JFrame("Foo",
                                 defaultCloseOperation = JFrame.EXIT_ON_CLOSE,
                                 size = (640, 480))
        self.btn = JButton("Check the file", actionPerformed=self.CheckFile)
        self.mainWindow.add(self.btn)
        self.mainWindow.visible = True

    def CheckFile(self, event):
        while True:
            line = self.myFile.readline()
            if not line:
                break
            print line

foo = Foo()

В конце концов, CheckFile() будет запущен, когда определенное сообщение будет получено в сокете. На данный момент я запускаю его из JButton.

Несмотря на то, что файл не тронут нигде в программе, и я не использую with в файле, я продолжаю получать ValueError: I/O operation on closed file, когда пытаюсь readline() его.

Исходное решение:

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

foo = Foo()
while True:
    if foo.myFile.closed == True:
        print "File is closed!"

Но тогда проблема исчезла! Или если я изменю его на:

foo = Foo()
foo.CheckFile()

тогда начинается начальная CheckFile(), что происходит прямо сейчас. Но затем, когда я нажимаю кнопку ~ через 5 секунд, исключение снова возникает!

После изменения бесконечного цикла до всего лишь pass, и обнаружив, что все еще работает, я пришел к выводу, что изначально, после создания экземпляра Foo, код приложения заканчивался, Foo выход из области действия, и, таким образом, foo.myFile выходит за пределы области действия и файл закрывается. Несмотря на это, качание удерживало окно открытым, что вызывало ошибки, когда я пытался работать в нераспечатанном файле.

Почему я все еще запутался:

Нечетная часть, если Foo вышел из сферы действия, почему тогда качание все еще можно было подключить к foo.CheckFile() вообще? Когда я нажимаю на JButton, не должна ли ошибка быть в том, что объект или метод больше не существует, а не метод, вызываемый успешно, и сообщение об ошибке при работе с файлом?

Моя следующая идея заключалась в том, что, возможно, когда JButton попытался вызвать foo.CheckFile() и обнаружил, что Foo больше не существует, он создал новый Foo, как-то пропустил его __init__ и перешел прямо к его CheckFile(). Однако, похоже, это не так. Если я изменю Foo.__init__, чтобы взять параметр, сохраните его в self.myNum и распечатайте его в CheckFile(), значение, которое я передаю, когда я создаю исходный объект, всегда присутствует. Это, по-видимому, предполагает, что Foo вообще не выходит за рамки, что возвращает меня туда, где я начал!!!

РЕДАКТИРОВАТЬ: Подчеркнул вопрос с соответствующей информацией из комментариев и удалил много комментариев.

4b9b3361

Ответ 1

* Начальный, частичный ответ (добавлен в вопрос) *

Думаю, я просто понял это. После foo = Foo(), без останова кода, чтобы поддерживать модуль занятым, казалось бы, объект перестает существовать, несмотря на то, что приложение все еще работает, а окно Swing делает вещи.

Если я это сделаю:

foo = Foo()
while True:
    pass

Затем все работает так, как я ожидал.

Я все еще запутался, что, как foo.CheckFile() вызывается вообще. Если проблема заключалась в том, что foo.myFile выходит из области видимости и закрывается, то почему foo.CheckFile() был вызван JButton?

Возможно, кто-то другой может дать лучший ответ.

Ответ 2

Я думаю, проблема возникает из-за того, что память разбивается на два типа на Java, кучу и не-кучу. Ваш экземпляр класса foo получает хранится в памяти кучи, а его метод CheckFile загружается в область метода памяти без кучи. После окончания script ссылок на foo больше нет, поэтому он будет помечен для сбора мусора, тогда как интерфейс Swing по-прежнему относится к CheckFile, поэтому он становится помеченным как используемый. Я предполагаю, что foo.myFile не считается статическим, поэтому он также сохраняется в памяти кучи. Что касается интерфейса Swing, он, по-видимому, по-прежнему отслеживается как используемый, пока окно открыто и обновляется диспетчером окон.


Изменить: ваше решение использования цикла while True является правильным, на мой взгляд. Используйте его для мониторинга событий и закрытия окна или чтения последней строки, выход из цикла и завершение программы.


Изменить 2: альтернативное решение - попробуйте foo наследовать от JFrame, чтобы заставить Swing держать постоянный указатель на него в своем основном цикле, пока окно открыто.