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

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

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

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 выходил из области видимости, и файл закрывался. Несмотря на это, Swing держал окно открытым, что приводило к ошибкам, когда я пытался работать с неоткрытым файлом.

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

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

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

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

Ответы [ 2 ]

4 голосов
/ 09 августа 2011

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

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

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

foo = Foo()
while True:
    pass

Тогда все будет работать так, как я ожидал.

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

Может быть, кто-то другой может дать лучший ответ.

2 голосов
/ 12 августа 2011

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


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


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

...