It looks like you're new here. If you want to get involved, click one of these buttons!
Hi, I am trying to read from PIPE in a Python macro.
I have nice stand-alone sample (it runs "ping 127.0.0.1" and reads/prints its output):
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui
class PipeReader(QtCore.QObject):
def __init__(self, parent=None):
super(PipeReader, self).__init__(parent)
self.process = QtCore.QProcess(self)
self.process.started.connect(self.on_started)
self.process.finished.connect(self.on_finished)
self.process.readyReadStandardOutput.connect(self.on_ready_read_standard_output)
command = "ping 127.0.0.1"
self.process.start(command)
def on_ready_read_standard_output(self):
result = self.process.readAllStandardOutput()
print("result = ", result)
def on_started(self):
print("started")
def on_finished(self):
print("finished")
app.quit()
app = QApplication([])
reader = PipeReader()
sys.exit(app.exec_())
I tried to port it to KLayout:
import pya
class PipeReader(pya.QObject):
def __init__(self, parent=None):
super(PipeReader, self).__init__(parent)
self.process = pya.QProcess(self)
self.process.finished = self.on_finished
self.process.readyReadStandardOutput = self.on_ready_read_standard_output
self.process.start("ping 127.0.0.1")
def on_ready_read_standard_output(self):
result = self.process.readAllStandardOutput()
print("result = ", result)
def on_finished(self):
print("finished")
#app = pya.QApplication()
reader = PipeReader()
#sys.exit(app.exec_())
But the only output I get is "finished". It takes some time to complete, so it really runs "ping", but no output is shown.
Maybe there is some problem in my QProcess config ?
Ps. The next code works almost perfectly (i.e. it shows "ping" output), but it locks the KLayout UI:
import subprocess
import io
process = subprocess.Popen("ping 127.0.0.1 -t", stdout=subprocess.PIPE, shell=True)
for line in io.TextIOWrapper(process.stdout):
print(line)
What could be wrong ?
Comments
Hi yaroslav,
I think Popen blocks because Qt implements it's own event loop (on Linux maybe it does a select, but I don't know if that helps keeping Popen active). There is a competition for CPU time and Popen looses.
The QProcess approach works, but you need to carefully control the way you're doing that. You're inside a live application and how you need to do this depends on what you want to achive. In the PyQt5 example you did a handshake and used "app.quit" to terminate the loop. You will also need to control the lifetime of the PipeReader object - as soon as the function finishes, the reader object will be deleted which ends your QProcess too.
The equivalent of your PyQt5 version above is:
run this with
If you want to run the process inside a menu function for example, you'll need to keep a reference to the reader object. The easiest way is to provide a parent in the constructor:
Note the "deleteLater" in "on_finished". This will actually remove the object once the operation has finished.
Regards,
Matthias
Hi Matthias,
thanks for the fast reply.
I want to run the script from menu, and with your help I was able to get the right response from the ping command on Centos 7 (just running your script):
But on Windows it is silent
Only "finished" is printed.
(I only removed "-c -4" from the ping command, as on Windows it has different keys)
Can you suggest how can I debug this ? Is it Qt or Python ?
On Centos 7 "About" box shows Qt 4.8.7 (Klayout 0.25.7)
And on Windows it is 5.6.2 (Klayout 0.25.7)
Update: for Windows case I have replaced
by
and it started to produce correct output.
Looks like there are some problems in readyReadStandardOutput slot or stdout on Windows.
Anyway that solves my problem.
Thanks a lot !