Re: [PyQt] graphical file tail

2013-06-25 Thread David Boddie
On Mon Jun 24 20:24:25 BST 2013, Eric Frederich wrote:

 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.

[...]

 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.

I notice that other messages have been talking about solving problems in
your original implementation, but how about trying a different approach?

The simple example below uses QProcess to show the output from a
command. In this case, tail -f file. It will stop the process when the
window is closed, but not the process creating the file, of course.

David


#!/usr/bin/env python

import sys

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class TailWidget(QTextBrowser):

def __init__(self, parent = None):
QTextBrowser.__init__(self, parent)
self.process = QProcess()
self.process.readyReadStandardOutput.connect(self.addStdout)
self.process.readyReadStandardError.connect(self.addStderr)
self.process.finished.connect(self.stop)
self.running = False

def start(self, command, arguments):
if self.running:
return

self.running = True
self.process.start(command, arguments)

def stop(self):
self.running = False

def addStdout(self):
self.append(QString.fromLocal8Bit(self.process.readAllStandardOutput()))

def addStderr(self):
self.append(QString.fromLocal8Bit(self.process.readAllStandardError()))

def closeEvent(self, event):
if self.running:
self.process.terminate()
self.process.waitForFinished(1000)

event.accept()

if __name__ == __main__:

app = QApplication(sys.argv)

if len(app.arguments()) != 2:
sys.stderr.write(Usage: %s file\n % app.arguments()[0])
sys.exit(1)

w = TailWidget()
w.start(tail, [-f, app.arguments()[1]])
w.show()
sys.exit(app.exec_())

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] graphical file tail

2013-06-25 Thread Eric Frederich
Thanks David,

This example works nicely.
It's nice to find out what you did wrong, but I'm always open to new
implementations.
In fact that is what I wanted, was someone to do it their way so I
could compare.
I'm sure I was doing something terribly wrong but didn't want to post
a do it for me email so I provided the implementation that I tried
;-)

Thanks,
~Eric


On Tue, Jun 25, 2013 at 8:22 AM, David Boddie david.bod...@met.no wrote:
 On Mon Jun 24 20:24:25 BST 2013, Eric Frederich wrote:

 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.

 [...]

 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.

 I notice that other messages have been talking about solving problems in
 your original implementation, but how about trying a different approach?

 The simple example below uses QProcess to show the output from a
 command. In this case, tail -f file. It will stop the process when the
 window is closed, but not the process creating the file, of course.

 David


 #!/usr/bin/env python

 import sys

 from PyQt4.QtCore import *
 from PyQt4.QtGui import *

 class TailWidget(QTextBrowser):

 def __init__(self, parent = None):
 QTextBrowser.__init__(self, parent)
 self.process = QProcess()
 self.process.readyReadStandardOutput.connect(self.addStdout)
 self.process.readyReadStandardError.connect(self.addStderr)
 self.process.finished.connect(self.stop)
 self.running = False

 def start(self, command, arguments):
 if self.running:
 return

 self.running = True
 self.process.start(command, arguments)

 def stop(self):
 self.running = False

 def addStdout(self):
 
 self.append(QString.fromLocal8Bit(self.process.readAllStandardOutput()))

 def addStderr(self):
 
 self.append(QString.fromLocal8Bit(self.process.readAllStandardError()))

 def closeEvent(self, event):
 if self.running:
 self.process.terminate()
 self.process.waitForFinished(1000)

 event.accept()

 if __name__ == __main__:

 app = QApplication(sys.argv)

 if len(app.arguments()) != 2:
 sys.stderr.write(Usage: %s file\n % app.arguments()[0])
 sys.exit(1)

 w = TailWidget()
 w.start(tail, [-f, app.arguments()[1]])
 w.show()
 sys.exit(app.exec_())

 ___
 PyQt mailing listPyQt@riverbankcomputing.com
 http://www.riverbankcomputing.com/mailman/listinfo/pyqt
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] graphical file tail

2013-06-24 Thread John Lee

On Mon, 24 Jun 2013, Eric Frederich wrote:


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:


You're not calling .wait on the threads, and you probably want to give 
e.g. your QObjects a parent where you can, so that Qt manages the lifetime 
of the wrapped C++ objects (e.g. pass in self to the parent arg of the 
QTextBrowser constructor).


But, I recommend doing it a different way: I find event-based code easier 
to think about than threads.  So, if you can use Qt5, you might want to do 
away with the threads and the tail subprocess and replace them with 
QFileSystemWatcher.  Use event-based code instead of the threads (I'm not 
talking about Qt events, I just mean hook up to the signals that that 
class emits and process a little input at a time so as to avoid blocking 
the UI, using QTimer where needed).  I say Qt5 because Qt4 isn't very 
friendly to this way of working since it uses threads in the 
implementation of QFileSystemWatcher.


Caveat: QFileSystemWatcher still has its problems, but the ones discussed 
at the URL below are more convenience issues than fundamental problems: I 
just found I had to experiment a bit to see when the different signals got 
emitted.


http://blog.rburchell.com/2012/03/qt-51-aka-when-qfilesystemwatcher-might.html

Caveat #2: I imagine QFileSystemWatcher does not support filesystems like 
NFS, at least on Linux kernels with inotify support (but don't take my 
word for it, check the source).



John
___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt


Re: [PyQt] graphical file tail

2013-06-24 Thread Eric Frederich
Thanks for the suggestions.  Unfortunately I do need to use Qt 4.6.2 from
RHEL 6.  This will also be on an NFS mounted drive.

This is for a GUI that monitors the output of jobs run on Sun Grid Engine
(SGE).  So its not that the files _happen_ to be on NFS, it's actually
_required_ that they are :-(

Any Qt4 help would be appreciated.
Am I cleaning up my tail processes correctly?  Is it just the QThreads I'm
screwing up?  Are there other hidden dangers with my implementation?
On Jun 24, 2013 7:25 PM, John Lee j...@pobox.com wrote:

 On Mon, 24 Jun 2013, Eric Frederich wrote:

  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:


 You're not calling .wait on the threads, and you probably want to give
 e.g. your QObjects a parent where you can, so that Qt manages the lifetime
 of the wrapped C++ objects (e.g. pass in self to the parent arg of the
 QTextBrowser constructor).

 But, I recommend doing it a different way: I find event-based code easier
 to think about than threads.  So, if you can use Qt5, you might want to do
 away with the threads and the tail subprocess and replace them with
 QFileSystemWatcher.  Use event-based code instead of the threads (I'm not
 talking about Qt events, I just mean hook up to the signals that that class
 emits and process a little input at a time so as to avoid blocking the UI,
 using QTimer where needed).  I say Qt5 because Qt4 isn't very friendly to
 this way of working since it uses threads in the implementation of
 QFileSystemWatcher.

 Caveat: QFileSystemWatcher still has its problems, but the ones discussed
 at the URL below are more convenience issues than fundamental problems: I
 just found I had to experiment a bit to see when the different signals got
 emitted.

 http://blog.rburchell.com/**2012/03/qt-51-aka-when-**
 qfilesystemwatcher-might.htmlhttp://blog.rburchell.com/2012/03/qt-51-aka-when-qfilesystemwatcher-might.html

 Caveat #2: I imagine QFileSystemWatcher does not support filesystems like
 NFS, at least on Linux kernels with inotify support (but don't take my word
 for it, check the source).


 John
 __**_
 PyQt mailing listPyQt@riverbankcomputing.com
 http://www.riverbankcomputing.**com/mailman/listinfo/pyqthttp://www.riverbankcomputing.com/mailman/listinfo/pyqt

___
PyQt mailing listPyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt