关于subprocess
和QProcess
已经有很多问题和答案,但我还没有找到我的问题的答案。因此,如果我在这一大堆部分令人困惑或过时的答案中没有找到答案,请原谅
这听起来像是一个简单的任务:在PyQt GUI应用程序中,我想启动一个独立的(子)进程。 在我的例子中:gnuplot,一个打印工具,带有选项'-p'(持久,即打印完成时保持窗口打开)。一旦启动,它应该继续作为独立(交互式)应用程序运行
文件
^{
代码:(我的精简示例,没有按预期工作)
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QVBoxLayout
from PyQt5.QtCore import pyqtSlot, QProcess
import sys, subprocess
class App(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(0,0,700,500)
self.layout = QVBoxLayout()
self.pb_plot_1 = QPushButton("Plot via subprocess")
self.pb_plot_1.clicked.connect(self.on_click_pb_plot_1)
self.layout.addWidget(self.pb_plot_1)
self.pb_plot_2 = QPushButton("Plot via QProcess")
self.pb_plot_2.clicked.connect(self.on_click_pb_plot_2)
self.layout.addWidget(self.pb_plot_2)
self.pb_plot_3 = QPushButton("Plot via QProcess and loading a file")
self.pb_plot_3.clicked.connect(self.on_click_pb_plot_3)
self.layout.addWidget(self.pb_plot_3)
self.setLayout(self.layout)
self.show()
@pyqtSlot()
def get_plot_code(self):
return '''
# some gnuplot code, in reality much longer
set term wxt
plot sin(x)
'''
def on_click_pb_plot_1(self):
gnuplotPath = r'gnuplot\bin\gnuplot'
gnuplotCode = self.get_plot_code()
proc = subprocess.Popen([gnuplotPath, '-p'], stdin=subprocess.PIPE)
proc.communicate(gnuplotCode.encode())
def on_click_pb_plot_2(self):
gnuplotPath = r'gnuplot\bin\gnuplot'
gnuplotCode = self.get_plot_code()
proc = QProcess(self)
proc.start(gnuplotPath, ["-p"])
proc.write(gnuplotCode.encode())
def on_click_pb_plot_3(self):
gnuplotPath = r'gnuplot\bin\gnuplot'
gnuplotFile = 'gnuplotFile.gp'
proc = QProcess(self)
proc.start(gnuplotPath, ["-p", gnuplotFile])
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
结果:
如果我按下按钮,每次gnuplot都会打开,并显示图形。到目前为止,好的。 但是,
通过子流程:gnuplot将作为交互式窗口工作,但在关闭gnuplot之前,我的PyQt应用程序将冻结(不响应)。
在^{close_fds=True
选项,它可能会执行我想要的操作,但在Windows中,这似乎与通过stdin=subprocess.PIPE
发送命令不起作用
Note that on Windows, you cannot set close_fds to true and also redirect the standard handles by setting stdin, stdout or stderr
那么,我如何使用subprocess
来实现它呢?添加proc.terminate()
没有帮助
通过QProcess:gnuplot将冻结,不会作为交互窗口工作(无响应)。如果我杀死gnuplot,我可以重新开始,但gnuplot会再次冻结
我也尝试过类似startDetached()
的东西,等等。。。没有成功
我可以想象,只要对代码做一点小小的修改,这个问题就可以得到解决。但我不知道如何改变。 因此,我确信这是我对文档的有限理解,我缺少合适的示例。 我的配置:Win10、Python 3.6.3、PyQt 5.11.3
更新:(上面的代码已更改,添加了第三个变体)
通过QProcess和读取文件(而不是将代码写入gnuplot)
a)gnuplot将创建绘图,b)任何内容都不会冻结,c)gnuplot保持交互,d)我可以独立关闭我的应用程序或gnuplot。
然而,我不想从磁盘读取gnuplot文件,但我想将代码发送到gnuplot(我想是发送到stdin
)
更新2:
也许这可以给能解释这件事的人一个暗示。它似乎取决于gnuplot版本。结果如下:
5.2.0 QWindowsPipeWriter::write failed. (The handle is invalid.)
5.2.2 QWindowsPipeWriter::write failed. (The handle is invalid.)
5.2.3 QWindowsPipeWriter::write failed. (The handle is invalid.)
5.2.4 QWindowsPipeWriter::write failed. (The handle is invalid.)
5.2.5 QWindowsPipeWriter::write failed. (The handle is invalid.)
5.2.6 works
5.2.7 works
5.2.8 works
5.4.0 freezing
5.4.1 freezing
好吧,@eyllanesc是对的。。。我将PyQt5从5.11.3更新到5.15.4,问题似乎不再出现。无论这是什么错误或不兼容
相关问题 更多 >
编程相关推荐