Python:在线程类中写入/追加文件出错

1 投票
1 回答
2399 浏览
提问于 2025-04-16 13:19

我想定期把一些测量数据写入一个txt文件,也就是做一些记录。

为了定期运行一个功能,有一个叫做RepeatTimer的类。而我用来更新文件的功能是VTlog(),代码如下。

class RepeatTimer(Thread):
    def __init__(self, interval, function, iterations=0, args=[], kwargs={}):
        Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.iterations = iterations
        self.args = args
        self.kwargs = kwargs
        self.finished = Event()

    def run(self):
        count = 0
        while not self.finished.isSet() and (self.iterations <= 0 or count < self.iterations):
            self.finished.wait(self.interval)
            if not self.finished.isSet():
                self.function(*self.args, **self.kwargs)
                count += 1

    def cancel(self):
        self.finished.set() 



def LogVT():
    tgt_picks = [t1,t2] #modify here for selective targets
    for tgt in tgt_picks:
        tt = tgt
        file = ('c:/vtlogs_%s.txt' % str(tt.target_name))
        x = str(tt.voltage('v_1p05_gfx_uncore')) + ', ' + str(tt.voltage('v_1p5_sm')) + ', ' + str(tt.temperature('pch_temp'))
        q = time.strftime('%m/%d/%y, %H:%M:%S')
        filehandle = open(file, 'a')
        filehandle.write('\n' + q + ', ' + x)
        filehandle.close()
        time.sleep(3)


logtimer = RepeatTimer(60.0, LogVT)
logtimer.start()

这里的'x'和'q'在离线查询时可以正常工作。t1和t2是一些连接了电压和温度测量设备的系统。api已经初始化好了。

我遇到的问题是,在运行时出现了这个错误:

Traceback (most recent call last):
  File "C:\Python25\lib\logging\__init__.py", line 750, in emit
    self.stream.write(fs % msg)
ValueError: I/O operation on closed file

有人能解释一下为什么会这样吗?

1 个回答

0

我觉得你应该先检查一下 open() 这个函数是不是执行成功了,也就是说,它是否真的返回了一个文件句柄,或者说有没有出现错误。在你对这个文件句柄调用 write()close() 之前,最好先确认一下。

------------更正-----------

你确实应该检查 open() 是否执行成功,但不是因为我之前提到的原因。如果 open() 不能打开文件,它会抛出一个 IOError 错误,所以这和你的问题没有关系。

正如Mat所建议的,问题可能是由于线程引起的。你可以尝试类似下面的代码:

...

    def run(self):
        count = 0
        # creating a lock
        lock = Lock()
        while not self.finished.isSet() and (self.iterations <= 0 or count < self.iterations):
            self.finished.wait(self.interval)
            if not self.finished.isSet():
                # call function with lock
                self.function(lock, *self.args, **self.kwargs)
                count += 1

...

def LogVT(lock):
    tgt_picks = [t1,t2] #modify here for selective targets
    for tgt in tgt_picks:
        tt = tgt
        file = ('c:/vtlogs_%s.txt' % str(tt.target_name))
        x = str(tt.voltage('v_1p05_gfx_uncore')) + ', ' + str(tt.voltage('v_1p5_sm')) + ', ' + str(tt.temperature('pch_temp'))
        q = time.strftime('%m/%d/%y, %H:%M:%S')
        # lock while doing file operations
        lock.acquire()
        filehandle = open(file, 'a')
        filehandle.write('\n' + q + ', ' + x)
        filehandle.close()
        # unlock
        lock.release()
        time.sleep(3)

...

撰写回答