Ich möchte ein interaktives Python-Terminal aus meiner Python-Anwendung aufrufen können. Einige, aber nicht alle Variablen in meinem Programm müssen dem Interpreter zur Verfügung gestellt werden.Einbetten eines Python-Interpreters in ein PyQT-Widget
Zur Zeit verwende ich eine untergeordnete und geänderte QPlainTextEdit
und route alle "Befehle" dort zu eval
oder exec
, und verfolgen Sie einen separaten Namespace in einem dict. Aber es muss einen eleganteren und robusteren Weg geben! Wie?
Hier ist ein Beispiel nur das tun, was ich will, aber es ist mit IPython und pyGTK ... http://ipython.scipy.org/moin/Cookbook/EmbeddingInGTK
Im Folgenden finden Sie, was ich habe zur Zeit. Aber es gibt so viele Eckfälle, dass ich wahrscheinlich einige vermisst habe. Es ist sehr langsam, versuche eine große Druckschleife ... Es muss einfacher und weniger fehleranfällig sein, ... Ich hoffe !!
Es ist die def runCommand(self)
Funktion, die der Schlüssel zum Verständnis meines Problems ist. Ich möchte es im Idealfall nicht verbessern, sondern den Inhalt durch etwas einfacheres und intelligenteres ersetzen.
Die Funktionalität der console.updateNamespace({'myVar1' : app, 'myVar2' : 1234})
Anweisung in "Haupt" ist auch wichtig.
import sys, os
import traceback
from PyQt4 import QtCore
from PyQt4 import QtGui
class Console(QtGui.QPlainTextEdit):
def __init__(self, prompt='$> ', startup_message='', parent=None):
QtGui.QPlainTextEdit.__init__(self, parent)
self.prompt = prompt
self.history = []
self.namespace = {}
self.construct = []
self.setGeometry(50, 75, 600, 400)
self.setWordWrapMode(QtGui.QTextOption.WrapAnywhere)
self.setUndoRedoEnabled(False)
self.document().setDefaultFont(QtGui.QFont("monospace", 10, QtGui.QFont.Normal))
self.showMessage(startup_message)
def updateNamespace(self, namespace):
self.namespace.update(namespace)
def showMessage(self, message):
self.appendPlainText(message)
self.newPrompt()
def newPrompt(self):
if self.construct:
prompt = '.' * len(self.prompt)
else:
prompt = self.prompt
self.appendPlainText(prompt)
self.moveCursor(QtGui.QTextCursor.End)
def getCommand(self):
doc = self.document()
curr_line = unicode(doc.findBlockByLineNumber(doc.lineCount() - 1).text())
curr_line = curr_line.rstrip()
curr_line = curr_line[len(self.prompt):]
return curr_line
def setCommand(self, command):
if self.getCommand() == command:
return
self.moveCursor(QtGui.QTextCursor.End)
self.moveCursor(QtGui.QTextCursor.StartOfLine, QtGui.QTextCursor.KeepAnchor)
for i in range(len(self.prompt)):
self.moveCursor(QtGui.QTextCursor.Right, QtGui.QTextCursor.KeepAnchor)
self.textCursor().removeSelectedText()
self.textCursor().insertText(command)
self.moveCursor(QtGui.QTextCursor.End)
def getConstruct(self, command):
if self.construct:
prev_command = self.construct[-1]
self.construct.append(command)
if not prev_command and not command:
ret_val = '\n'.join(self.construct)
self.construct = []
return ret_val
else:
return ''
else:
if command and command[-1] == (':'):
self.construct.append(command)
return ''
else:
return command
def getHistory(self):
return self.history
def setHisory(self, history):
self.history = history
def addToHistory(self, command):
if command and (not self.history or self.history[-1] != command):
self.history.append(command)
self.history_index = len(self.history)
def getPrevHistoryEntry(self):
if self.history:
self.history_index = max(0, self.history_index - 1)
return self.history[self.history_index]
return ''
def getNextHistoryEntry(self):
if self.history:
hist_len = len(self.history)
self.history_index = min(hist_len, self.history_index + 1)
if self.history_index < hist_len:
return self.history[self.history_index]
return ''
def getCursorPosition(self):
return self.textCursor().columnNumber() - len(self.prompt)
def setCursorPosition(self, position):
self.moveCursor(QtGui.QTextCursor.StartOfLine)
for i in range(len(self.prompt) + position):
self.moveCursor(QtGui.QTextCursor.Right)
def runCommand(self):
command = self.getCommand()
self.addToHistory(command)
command = self.getConstruct(command)
if command:
tmp_stdout = sys.stdout
class stdoutProxy():
def __init__(self, write_func):
self.write_func = write_func
self.skip = False
def write(self, text):
if not self.skip:
stripped_text = text.rstrip('\n')
self.write_func(stripped_text)
QtCore.QCoreApplication.processEvents()
self.skip = not self.skip
sys.stdout = stdoutProxy(self.appendPlainText)
try:
try:
result = eval(command, self.namespace, self.namespace)
if result != None:
self.appendPlainText(repr(result))
except SyntaxError:
exec command in self.namespace
except SystemExit:
self.close()
except:
traceback_lines = traceback.format_exc().split('\n')
# Remove traceback mentioning this file, and a linebreak
for i in (3,2,1,-1):
traceback_lines.pop(i)
self.appendPlainText('\n'.join(traceback_lines))
sys.stdout = tmp_stdout
self.newPrompt()
def keyPressEvent(self, event):
if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
self.runCommand()
return
if event.key() == QtCore.Qt.Key_Home:
self.setCursorPosition(0)
return
if event.key() == QtCore.Qt.Key_PageUp:
return
elif event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Backspace):
if self.getCursorPosition() == 0:
return
elif event.key() == QtCore.Qt.Key_Up:
self.setCommand(self.getPrevHistoryEntry())
return
elif event.key() == QtCore.Qt.Key_Down:
self.setCommand(self.getNextHistoryEntry())
return
elif event.key() == QtCore.Qt.Key_D and event.modifiers() == QtCore.Qt.ControlModifier:
self.close()
super(Console, self).keyPressEvent(event)
welcome_message = '''
---------------------------------------------------------------
Welcome to a primitive Python interpreter.
---------------------------------------------------------------
'''
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
console = Console(startup_message=welcome_message)
console.updateNamespace({'myVar1' : app, 'myVar2' : 1234})
console.show();
sys.exit(app.exec_())
Erstes Ergebnis von Google zu unterstützen: http: //doc.trolltech.com/qq/qq23-pythonqt.html und von der zweiten Seite: http://wiki.python.org/moin/EmpedingPyQtTutorial. Passen diese zu Ihren Bedürfnissen? Nochmal: http://stackoverflow.com/questions/2742636/how-to-embed-the-python-interpreter-in-a-qt-app –
Nein, meine Anwendung ist in Python geschrieben. Diese Seiten betreffen die Umhüllung von C (++) Anwendungen in Python und die Einbettung von Python in C (++) Anwendungen. – Mathias
Bitte vergessen Sie meinen vorherigen Kommentar –