[question]redirecting stdout to display via widget?
Hi everyone.
I'm very new to PyQt4 (its my fifth day) and I would like some help with this program. I'm getting familiar with different classes and have only started to wrap my head around the SIGNAL/SLOT concept.
I want to redirect the output of the system call in the code to QTextBrowser, but I'm missing something basic here. Maybe use a different widget? conceptual mistake?
Code:
import sys
from PyQt4 import QtGui, QtCore
from subprocess import Popen, PIPE
def __init__(self, parent=None):
QtGui.
QWidget.__init__
(self, parent
)
self.setWindowTitle('PTCL')
self.
setWindowIcon(QtGui.
QIcon('/usr/share/pixmaps/idle.xpm'))
self.connect(dial, QtCore.SIGNAL('clicked()'), self.slotDial)
self.connect(quit, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit()'))
output
= QtGui.
QLabel('Output')
self.connect(dial, QtCore.SIGNAL('clicked()'), self.showOutput)
grid.setSpacing(10)
grid.addWidget(dial, 1, 0)
grid.addWidget(quit, 1, 1)
grid.addWidget(output, 2, 0)
grid.addWidget(displaybox, 3, 0, 5, 3)
self.setLayout(grid)
self.resize(190, 50)
def slotDial(self):
x = Popen(("wvdial", "ptcl"), stdout=PIPE).stdout
f = x.readline()
x.close()
def showOutput(self):
displaybox.append(f)
dg = dialerGui()
dg.show()
sys.exit(app.exec_())
Any help will be much appreciated.
Re: [question]redirecting stdout to display via widget?
Here is the traceback:
[sbjaved@pasaris Code]$ python ptcl_dialer_testing.py
--> WvDial: Internet dialer version 1.60
--> Warning: section [Dialer ptcl] does not exist in wvdial.conf.
--> Cannot open /dev/modem: Device or resource busy
--> Cannot open /dev/modem: Device or resource busy
--> Cannot open /dev/modem: Device or resource busy
Traceback (most recent call last):
File "ptcl_dialer_testing.py", line 46, in showOutput
displaybox.append(f)
NameError: global name 'displaybox' is not defined
This output only displays in the terminal. I would like to redirect it to the QTextBrowser widget.
Re: [question]redirecting stdout to display via widget?
Have you considered using QProcess instead of that popen function? It provides methods to read a process's output, like QProcess::readAllStandardOutput(). Or maybe Python itself provides a way to execute external processes and return their output, like Perl or Ruby do with ``?
Re: [question]redirecting stdout to display via widget?
I would use a simple system() call, I'm sure Python has one. It's the most simple way to fetch output of a short running program.
Re: [question]redirecting stdout to display via widget?
Quote:
Originally Posted by
wysota
I would use a simple system() call, I'm sure Python has one. It's the most simple way to fetch output of a short running program.
The subprocess module allows you to redirect the stderr/stdout which in my case is linked to the variable 'f'. The problem I'm having is linking the variable 'f' defined in showOutput function to 'displaybox'(QTextBrowser) defined in __init__ function. Python doesn't recognize the local variable 'displaybox' (see the Traceback) and I'm stumped thinking of a way to link the output to the widget.
In Line 21 of the code, I've linked the signal clicked() emitted by the dial QPushButton widget to the showOutput function:
displaybox = QtGui.QTextBrowser()
self.connect(dial, QtCore.SIGNAL('clicked()'), self.showOutput)
Maybe something wrong here?
Re: [question]redirecting stdout to display via widget?
Quote:
Originally Posted by
rexi
Have you considered using
QProcess instead of that popen function? It provides methods to read a process's output, like
QProcess::readAllStandardOutput(). Or maybe Python itself provides a way to execute external processes and return their output, like Perl or Ruby do with ``?
I tried using QProcess following the guide posted here. But that guide is for PyQt and I couldn't get it to work. Maybe if you could post a simple PyQt4 QProcess example, it would be very helpful...
Thanks for replying.
Re: [question]redirecting stdout to display via widget?
Sorry, but I don't really speak enough Python to provide an example ;)
But looking at your code, I guess dialogbox is not a member variable of your class, but local to the __init__ method. Aren't members accessed by something like self.displaybox?
Re: [question]redirecting stdout to display via widget?
Quote:
Originally Posted by
sbjaved
I tried using QProcess following the guide posted
here. But that guide is for PyQt and I couldn't get it to work. Maybe if you could post a simple PyQt4 QProcess example, it would be very helpful...
Thanks for replying.
Hi,
I suffered from the same. The example you're referring to, is indeed not working flawless under PyQt4.
I've been able to "translate" it to PyQt4. I'm using Eric4 as my IDE and created a project for the corrected version. It's working very good now...
If you're interested in the code, let me know. It needs some more cleaning up, but I think I can manage to give it to you within a couple of days.
Best rgds,
--Geert
Re: [question]redirecting stdout to display via widget?
Quote:
Originally Posted by
GeertVc
Hi,
I suffered from the same. The example you're referring to, is indeed not working flawless under PyQt4.
I've been able to "translate" it to PyQt4. I'm using Eric4 as my IDE and created a project for the corrected version. It's working very good now...
If you're interested in the code, let me know. It needs some more cleaning up, but I think I can manage to give it to you within a couple of days.
Best rgds,
--Geert
I'm very interested. Please email me the code at sbjaved AT gmail.
Re: [question]redirecting stdout to display via widget?
Hi folks!
I'm a newbie and i'm trying to "translate" This tutorial to PyQt4.
I don't get the output of the process on the textBrowser.
Can anyone help me?
Fantagol
test1.py
Code:
#!/usr/bin/python
from time import sleep
print "this is"
print "a test""
i=0
while 1:
print i
sleep(1)
if i == 5:
#os.kill(os.getpid(),signal.SIGKILL)
i +=1
CapturingOutputfromProcess.py
Code:
import sys,os,signal
from PyQt4 import QtCore, QtGui
def __init__(self):
#Layout
self.stopButton.setEnabled(False)
layout.setSpacing(8)
layout.addWidget(self.textBrowser, 0, 0)
layout.addWidget(self.lineEdit, 1, 0)
layout.addWidget(self.startButton, 1, 1)
layout.addWidget(self.stopButton, 1, 2)
#Connection
self.connect(self.lineEdit, QtCore.SIGNAL("returnPressed()"), self.startCommand)
self.connect(self.startButton, QtCore.SIGNAL("clicked()"), self.startCommand)
self.connect(self.stopButton, QtCore.SIGNAL("clicked()"), self.stopCommand)
#Process
self.connect(self.process, QtCore.SIGNAL("readyReadStdout()"), self.readOutput)
self.connect(self.process, QtCore.SIGNAL("readyReadStderr()"), self.readErrors)
self.connect(self.process, QtCore.SIGNAL("processExited()"), self.resetButtons)
def startCommand(self):
self.
process.
start("python test1.py", QtCore.
QStringList(["my_file.tex"])) StartString="Process started with pid: "+str(self.process.pid())
print StartString
self.textBrowser.append(StartString)
print self.process.ProcessState()
#self.process.close()
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
#self.textBrowser.clear()
#~ if not self.process.start():
#~ self.textBrowser.setText(
#~ QtGui.QString("*** Failed to run %1 ***").arg(self.lineEdit.text())
#~ )
#~ self.resetButtons()
#~ return
def stopCommand(self):
self.resetButtons()
print "Stop process, PID was: ", self.process.pid()
os.kill(self.process.pid(), signal.SIGKILL)
#QtCore.QTimer.singleShot(5000, self.process, SLOT("kill()"))
def readOutput(self):
print self.process.readStdout()
self.
textBrowser.
append(QtGui.
QString(self.
process.
readStdout())) if self.process.isRunning()==False:
self.textBrowser.append("\n Completed Successfully")
def readErrors(self):
self.
textBrowser.
append("error: " + QtGui.
QString(self.
process.
readLineStderr())) def resetButtons(self):
self.startButton.setEnabled(True)
self.stopButton.setEnabled(False)
if __name__ == "__main__":
window = Window()
window.show()
sys.exit(app.exec_())
Re: [question]redirecting stdout to display via widget?
First you read output from the process and print it to the screen and then you read it again and try to add it to the widget. Since you have already read the output, nothing remains to be read and you don't get anything in your widget.
Re: [question]redirecting stdout to display via widget?
Tks 1k wysota, for your answer, but if I change readOutput in
Code:
def readOutput(self):
print self.process.readStdout()
I don't get any output too, and futher the process is not running,
according to QProcess.ProcessState = 0.
bye
Fantagol
Re: [question]redirecting stdout to display via widget?
When are you reading the state? Just after calling start()? If so then the process is not started yet at that point. Either way make sure you pass correct arguments to start(). To me it seems "python" is the name of your program and "test1.py" and "my_file.tex" are its arguments. Unless of course you do have an executable called "python test1.py" but that would be weird.
Re: [question]redirecting stdout to display via widget?
Thanks very much for your precious help wysota, but nothing happens.This is what I did:
According to this Documentation
I add this connection
Code:
self.connect(self.process, QtCore.SIGNAL("started()"), self.processIsStarted)
add a new function:
Code:
def processIsStarted(self):
print "according to SIGNAL STARTED() process with pid: ",str(self.process.pid()),"is started"
print "Its State is ", self.process.ProcessState()
and change the calling:
Code:
def startCommand(self):
self.
process.
start("python", QtCore.
QStringList(["test1.py",
"my_file.txt"])) StartString="Process started with pid: "+str(self.process.pid())
print StartString
self.textBrowser.append(StartString)
print self.process.ProcessState()
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
To starts a given program, i have to use this instantiation?
Is QIODevice.OpenMode important?
tks to all
fantagol
Re: [question]redirecting stdout to display via widget?
No, the mode is not important for you. Does it work if you change test1.py to an absolute path? It is likely your file cannot be found. Although in this case python SHOULD start, it would just quit immediately. Unless your python binary cannot be found as well.
2 Attachment(s)
Re: [question]redirecting stdout to display via widget?
Here the new files:
Attachment 6269
Attachment 6268
I think that the python script "test1.py" is started by my code, but self.process.ProcessState() say me quite another thing. I change the test1.py with a simple infinite print cycle:
Code:
#!/usr/bin/python
print "test1"
print "test2"
#from time import sleep
i=0
while 1:
print i
#sleep(1)
if i == 5:
#os.kill(os.getpid(),signal.SIGKILL)
pass
i +=1
I think that the new process is started because i can see its pid on "System Monitor", and its cpu occupation. This is the new attemp in the script:
Code:
def startCommand(self):
self.
process.
start("python", QtCore.
QStringList(["/home/MyUserAccount/test1.py"])) StartString="Process started with pid: "+str(self.process.pid())
print StartString
self.textBrowser.append(StartString)
print self.process.ProcessState()
#self.process.close()
self.startButton.setEnabled(False)
self.stopButton.setEnabled(True)
#self.textBrowser.clear()
def processIsStarted(self):
print "according to SIGNAL STARTED() process with pid: ",self.process.pid()
def stopCommand(self):
print "Attempt to stop a process with Pid: ", str(self.process.pid())
print "What is the State of this process?"
print "Its State is ", self.process.ProcessState()
self.resetButtons()
print "Stop process, PID was: ", self.process.pid()
os.kill(self.process.pid(), signal.SIGKILL)
When i run $python CapturingOutputfromProcess03.py , and press the button start, the message is shown correctly on the textbrowser "Process started with pid: 2277":
Code:
Process started with pid: 2277
0
according to SIGNAL STARTED() process with pid: 2277
A new pid appears on the System Monitor with its CPU occupation.
Then, when I press the stop button, the gui disappears and the terminal reveals this:
Code:
Attempt to stop a process with Pid: 2283
What is the State of this process?
Its State is 0
Stop process, PID was: 2283
I hope we can reach a solution.
Thanks a lot
Re: [question]redirecting stdout to display via widget?
But what's wrong exactly? It seems the script gets executed, what more do you want?
Re: [question]redirecting stdout to display via widget?
Quote:
Originally Posted by
wysota
But what's wrong exactly? It seems the script gets executed, what more do you want?
I want to redirect the standard output, and print on the textBrowser what comes from test1.py. I don't see anything append on the widget by test1.py.
Re: [question]redirecting stdout to display via widget?
Then connect to the appropriate signal and read the output from within the slot.
Re: [question]redirecting stdout to display via widget?
I'm looking for the solution from many days!!
This is the SIGNAL:
Code:
self.connect(self.process, QtCore.SIGNAL("readyReadStdout()"), self.readOutput)
self.connect(self.process, QtCore.SIGNAL("readyReadStderr()"), self.readErrors)
and this is the SLOT:
Code:
def readOutput(self):
#print self.process.readStdout()
self.
textBrowser.
append(QtGui.
QString(self.
process.
readStdout())) #if self.process.isRunning()==False:
# self.textBrowser.append("\n Completed Successfully")
def readErrors(self):
self.
textBrowser.
append("error: " + QtGui.
QString(self.
process.
readLineStderr()))
....Where is the mistake?