I'm trying to tail several files graphically. I have been trying to find a way to tail several files in a GUI without much luck at all. I get errors from tail saying broken pipe. I get PyQt errors saying underlying C++ objects have been destroyed. I get other Qt errors saying that threads are still running when the application exits etc....
The implementation posted below seems to suffer from the following errors. Not all the time. It depends. QThread: Destroyed while thread is still running QWaitCondition::wakeAll(): mutex lock failure: Please tell me what I'm doing wrong. Feel free to tell me if I'm doing something bone-headed. Basically, I want to graphically tail files and when the GUI closes the tail subprocesses are killed. Seems like a simple request, but I can't get it right. #!/usr/bin/env python from PyQt4.QtCore import * from PyQt4.QtGui import * import os from subprocess import Popen, PIPE class Tailer(QThread): def __init__(self, fname, parent=None): super(Tailer, self).__init__(parent) self.fname = fname self.connect(self, SIGNAL('finished()'), self.cleanup) def cleanup(self): print 'CLEANING UP' self.p.kill() print 'killed' def run(self): command = ["tail", "-f", self.fname] print command self.p = Popen(command, stdout=PIPE, stderr=PIPE) while True: line = self.p.stdout.readline() self.emit(SIGNAL('newline'), line.rstrip()) if not line: print 'BREAKING' break def foo(self): self.p.kill() class TailWidget(QWidget): def __init__(self, fnames, parent=None): super(TailWidget, self).__init__(parent) layout = QGridLayout() self.threads = {} self.browsers = {} for i, fname in enumerate(fnames): if not os.path.exists(fname): print fname, "doesn't exist; creating" p = Popen(['touch', fname], stdout=PIPE, stderr=PIPE) out, err = p.communicate() ret = p.wait() assert ret == 0 t = Tailer(fname, self) self.threads[fname] = t b = QTextBrowser() self.browsers[fname] = b layout.addWidget(QLabel('Tail on %s' % fname), 0, i) layout.addWidget(b, 1, i) self.connect(t, SIGNAL("newline"), b.append) t.start() self.setLayout(layout) def closeEvent(self, event): for fname, t in self.threads.items(): t.foo() if __name__ == '__main__': import sys app = QApplication(sys.argv) tw = TailWidget(sys.argv[1:]) tw.show() sys.exit(app.exec_()) _______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt