如何解决如何使用子进程或 QProcess 启动独立的 gnuplot 进程?
已经有很多关于subprocess
和QProcess
的问题和答案,但我还没有找到我的问题的答案。因此,如果我没有在这部分令人困惑或过时的答案中找到答案,请原谅。
这听起来像是一个简单的任务:在 PyQt GUI 应用程序中,我想启动一个独立的(子)进程。 就我而言:gnuplot,一种绘图工具,带有选项“-p”(持久性,即在绘图完成时保持窗口打开)。启动后,它应继续作为独立(交互式)应用程序运行。
文档
QProcess
和 subprocess
没有进一步帮助我。
代码:(我精简的最小示例,它没有按预期工作)
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,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 将作为交互式窗口工作,但我的 PyQt 应用程序将冻结(不响应),直到我关闭 gnuplot。
使用 subprocess.Popen
时,似乎有选项 close_fds=True
,它应该可以满足我的要求,但在 Windows 中,这似乎无法与通过 stdin=subprocess.PIPE
发送命令一起使用。
请注意,在 Windows 上,您不能将 close_fds 设置为 true,也不能将 通过设置 stdin、stdout 或 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,问题似乎不再出现。无论这是什么错误或不兼容...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。