Python 通过GUI重定向stdin
我有一个非常基本的应用程序,它打算在一个Python 通过GUI重定向stdin,python,pyqt,pyqt4,stdin,io-redirection,Python,Pyqt,Pyqt4,Stdin,Io Redirection,我有一个非常基本的应用程序,它打算在一个textEdit组件上评估给定的Python代码,并在另一个组件上显示结果 import sys
textEdit
组件上评估给定的Python代码,并在另一个组件上显示结果
import sys
from PyQt4 import QtGui
from cStringIO import StringIO
class SampleGUI(QtGui.QWidget):
def __init__(self):
super(SampleGUI, self).__init__()
self.initGUI()
def initGUI(self):
self.code = QtGui.QTextEdit()
self.result = QtGui.QTextEdit()
btn = QtGui.QPushButton('Evaluate')
btn.clicked.connect(self.evaluate)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(self.code)
vbox.addWidget(btn)
vbox.addWidget(self.result)
self.setLayout(vbox)
self.show()
def evaluate(self):
source_code = str(self.code.toPlainText())
old_stdout = sys.stdout
redirected_output = sys.stdout = StringIO()
exec source_code
sys.stdout = old_stdout
self.result.setText(redirected_output.getvalue())
def main():
app = QtGui.QApplication([])
s = SampleGUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
到目前为止,它工作得很好,您不需要输入值。假设您使用python samplegui.py
从控制台运行脚本,如果您碰巧在第一个文本框中键入类似的内容:
a = 3
print 5 + a
b = input()
print 1 + b
然后按下Evaluate
,应用程序希望从控制台输入值。输入一些值并按enter键后,它将继续并正确计算
我想要实现的是将stdin
重定向到一个我可以在GUI
本身中操作的组件
我该怎么做?理想情况下,我希望使用Python解释器样式,在这种样式中,输出和输入以交互方式进行。另一个选项是在应用程序等待输入时以某种方式处理/捕获信号,并显示输入对话框
编辑:
事实证明,这比我想象的要容易。在这里,您可以看到使用QInputDialog
截取的带有sys.stdin
的脚本版本,因此用户可以从GUI
输入值
import sys
from PyQt4 import QtGui
from cStringIO import StringIO
class InputGUI():
def __init__(self, parentWidget):
self.parentWidget = parentWidget
def readline(self):
text, ok = QtGui.QInputDialog.getText(self.parentWidget, 'Introduce value', 'Value:')
if ok:
return str(text)
else:
return ''
class SampleGUI(QtGui.QWidget):
def __init__(self):
super(SampleGUI, self).__init__()
self.initGUI()
def initGUI(self):
self.code = QtGui.QTextEdit()
self.result = QtGui.QTextEdit()
btn = QtGui.QPushButton('Evaluate')
btn.clicked.connect(self.evaluate)
vbox = QtGui.QVBoxLayout()
vbox.addWidget(self.code)
vbox.addWidget(btn)
vbox.addWidget(self.result)
self.setLayout(vbox)
self.show()
def evaluate(self):
source_code = str(self.code.toPlainText())
streams = sys.stdin, sys.stdout
sys.stdin = InputGUI(self)
redirected_output = sys.stdout = StringIO()
exec source_code
sys.stdin, sys.stdout = streams
self.result.setText(redirected_output.getvalue())
def main():
app = QtGui.QApplication([])
s = SampleGUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我将用实现文件描述符协议的自定义类的实例替换
sys.stdin
。然后,您可以简单地决定当用户希望通过input()
或sys.stdin.readline()
读取某个内容时应该发生什么
至于实现一个文件描述符:实现本文中涉及的所有方法。此外,您可能希望实现,因此您的自定义sys.stdin
可以与with
语句一起使用
但是,请注意,如果用户再次更换
sys.stdin
自己,仍然可能会射中自己的脚,但至少这似乎比调用input()
的人更不可能,谢谢你为我指明了正确的方向@Christian Aichinger。我创建了一个实现readline()
的类,这是我现在唯一需要的方法。不用担心重新替换sys.stdin,我控制要计算的代码(即由解析器生成)。我将编辑问题以添加已修改的脚本,这样它将接受来自QInputDialog
的输入。