¿Por qué mi archivo se cierra si no hago nada con él durante un tiempo?

Situación original:

La aplicación en la que estoy trabajando en este momento recibirá una notificación de otra aplicación cuando un archivo en particular haya agregado datos y esté listo para ser leído. En este momento tengo algo como esto:

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() 

Finalmente, CheckFile () se activará cuando se reciba un determinado mensaje en un socket. En este momento, lo estoy activando desde un JButton.

A pesar del hecho de que el archivo no se toca en ninguna otra parte del progtwig, y ​​no estoy usando with el archivo, sigo obteniendo ValueError: I/O operation on closed file cuando bash readline() .

Solución inicial:

    Al intentar averiguar cuándo se estaba cerrando exactamente el archivo, cambié el código de mi aplicación a:

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

    Pero luego el problema se fue! O si lo cambio a:

     foo = Foo() foo.CheckFile() 

    entonces el CheckFile() inicial, que ocurre de inmediato, funciona. Pero luego, cuando hago clic en el botón ~ 5 segundos después, ¡la excepción vuelve a aparecer!

    Después de cambiar el bucle infinito para simplemente pass , y al descubrir que todo seguía funcionando, mi conclusión fue que inicialmente, sin nada más que hacer después de crear una instancia de Foo , el código de la aplicación estaba terminando, foo estaba fuera de scope, y por lo tanto, foo.myFile estaba fuera de scope y el archivo estaba siendo cerrado. A pesar de esto, swing mantenía la ventana abierta, lo que provocaba errores cuando intentaba operar en un archivo sin abrir.

    Por qué todavía estoy confundido:

    La parte extraña es que, si foo hubiera salido del scope, ¿por qué entonces el columpio todavía podía engancharse en foo.CheckFile() ? Cuando hago clic en el JButton, ¿no debería ser el error que el objeto o el método ya no existe, en lugar de que el método se llame con éxito y que dé un error en la operación del archivo?

    Mi siguiente idea fue que tal vez, cuando JButton intentó llamar a foo.CheckFile() y descubrió que ya no existía, creó un nuevo Foo , de alguna manera se saltó su __init__ y fue directamente a su CheckFile() . Sin embargo, este tampoco parece ser el caso. Si Foo.__init__ para tomar un parámetro, guárdelo en self.myNum e imprímalo en CheckFile() , el valor que paso cuando instancia el objeto inicial siempre está ahí. Esto parece sugerir que foo no está fuera del scope en absoluto, ¡¡¡¡¡¡¡¡¡¡¡¡así que eso me pone de vuelta donde comencé !!!

    EDITAR: Se ordenó la pregunta con información relevante de los comentarios y se eliminaron muchos de dichos comentarios.

    * Respuesta inicial, parcial (agregada a la pregunta) *

    Creo que acabo de resolver esto. Después de foo = Foo() , sin que quede ningún código para mantener el módulo ocupado, parece que el objeto deja de existir, a pesar del hecho de que la aplicación todavía se está ejecutando, con una ventana de Swing haciendo cosas.

    Si hago esto:

     foo = Foo() while True: pass 

    Entonces todo funciona como yo esperaría.

    Sin embargo, todavía estoy confundido, en cuanto a cómo se llamaba a foo.CheckFile (). Si el problema era que foo.myFile estaba fuera de scope y estaba cerrado, entonces, ¿por qué el JButton pudo llamar a foo.CheckFile ()?

    Tal vez alguien más puede proporcionar una mejor respuesta.

    Creo que el problema surge de que la memoria se divide en dos tipos en Java, heap y no heap. Su instancia de clase foo se almacena en la memoria heap mientras que su método CheckFile se carga en el área de métodos de la memoria no heap. Una vez que finaliza la secuencia de comandos, no hay más referencias a foo por lo que se marca para la recolección de basura, mientras que la interfaz de Swing aún hace referencia a CheckFile , por lo que se marca como en uso. Supongo que foo.myFile no se considera estático, por lo que también se almacena en la memoria del montón. En cuanto a la interfaz Swing, es probable que se siga rastreando en uso mientras la ventana esté abierta y el administrador de ventanas la esté actualizando.


    Editar: en mi opinión, su solución de usar un bucle while True es correcta. Úselo para monitorear eventos y cuando la ventana se cierre o cuando se lea la última línea, salga del ciclo y deje que el progtwig termine.


    Edición 2: solución alternativa: intente que foo herede de JFrame para que Swing mantenga un puntero persistente en su bucle principal mientras la ventana esté abierta.