如果我暂时没有对它做任何事情,为什么我的文件会被关闭?

时间:2011-08-09 05:48:41

标签: python file swing jvm jython

原始情况:

我正在处理的应用程序将在特定文件添加了数据并准备好读取时接收来自其他应用程序的通知。目前我有这样的事情:

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,但在尝试{{1}时,我仍然会收到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() 起作用。但是当我在5秒钟后点击按钮时,再次引发异常!

将无限循环更改为CheckFile()后,发现一切仍然有效,我的结论是,最初,在实例化pass后没有任何事情要做,应用程序代码结束了, Foo超出范围,因此foo超出了范围,文件正在关闭。尽管如此,swing仍然保持窗口打开,当我尝试操作未打开的文件时,这会导致错误。

为什么我仍然感到困惑:

奇怪的是,如果foo.myFile已超出范围,那么为什么摇摆仍然能够挂钩foo呢?当我点击JButton时,错误不应该是对象或方法不再存在,而不是成功调用方法并在文件操作上给出错误?

我的下一个想法是,当JButton试图调用foo.CheckFile()并发现foo.CheckFile()不再存在时,它会创建一个新的foo,不知何故跳过其Foo然后直奔__init__。但是,情况似乎也不是这样。如果我修改CheckFile()以获取参数,将其存储在Foo.__init__中,并在self.myNum中打印出来,我在实例化初始对象时传入的值始终存在。这似乎表明CheckFile()根本没有超出范围,这让我回到了我开始的地方!

编辑:用评论中的相关信息整理提问,并删除了很多评论。

2 个答案:

答案 0 :(得分:4)

*初始,部分答案(已添加至问题)*

我想我只想出了这个。在foo = Foo()之后,没有任何代码可以让模块保持忙碌状态,看起来对象不再存在,尽管应用程序仍在运行,Swing窗口正在运行。

如果我这样做:

foo = Foo()
while True:
    pass

然后一切都按照我的预期运作。

我仍然感到困惑,至于如何调用foo.CheckFile()。如果问题是foo.myFile超出范围并被关闭,那么为什么joo.CheckFile()能够被JButton调用?

也许其他人可以提供更好的答案。

答案 1 :(得分:2)

我认为问题出现在Java,堆和非堆中将内存分区为two types。您的类实例foo在加载方法CheckFile时存储在堆内存中进入非堆内存的方法区域。脚本完成后,不再有对foo的引用,因此它被标记为垃圾收集,而Swing接口仍然引用CheckFile,因此它被标记为正在使用。我假设foo.myFile不被认为是静态的,所以它也存储在堆内存中。至于Swing界面,只要窗口打开并由窗口管理器更新,它就可能仍然被跟踪为使用中。


编辑:在我看来,使用while True循环的解决方案是正确的。使用它来监视事件,当窗口关闭或读取最后一行时,退出循环并让程序完成。


编辑2:替代解决方案 - 尝试从foo继承JFrame以使Swing在其主循环中保持持久指针,只要窗口打开。