Versión: 2.7
Este código de fuente puede utilizarse con varios objetivos. Trata de una consola gráfica de Python, similar a la integrada con IDLE, que hace uso del módulo code
para ejecutar el código, PyQt para el diseño de la interfaz gráfica junto con QScintilla
, una portación del control para edición de código Scintilla. A través del syntax highlighting pretende proveer una simple consola de mayor comodidad en comparación a la que se distribuye junto con CPython. Podrá ser de utilidad para aquellos usuarios que deseen explorar código en acción de PyQt, el control QScintilla
y el módulo estándar code
.
A lo largo del código podrán observar los múltiples comentarios que espero que les sean de utilidad para su comprensión.
El código requiere la instalación del paquete PyQt 4 y la versión de Python 2.7. Para aquellos usuarios de Windows que quieran ejecutar el script sin los requerimientos anteriores pueden descargar el archivo ejecutable desde aquí.
#!/usr/bin/env python # -*- coding: utf-8 -*- # # main.py # # Copyright 2013 Recursos Python - www.recursospython.com # import sys from code import InteractiveConsole from threading import Thread from time import sleep from PyQt4.QtCore import QObject, QRect, Qt, pyqtSignal from PyQt4.QtGui import QApplication, QMainWindow from PyQt4.Qsci import QsciScintilla, QsciLexerPython class GUIConsole(Thread, InteractiveConsole): def __init__(self, scintilla): Thread.__init__(self) InteractiveConsole.__init__(self) self.scintilla = scintilla def write(self, string): """ Enviar el output al editor en lugar de la consola. """ self.scintilla.append(string) def raw_input(self, prompt_unused): """ Leer la entrada desde el editor en lugar de la consola. """ self.scintilla.append(">>> ") # Ignorar el argumento self.scintilla.SendScintilla( self.scintilla.SCI_GOTOPOS, len(self.scintilla.text()) ) return self.scintilla.get_input() def run(self): try: self.interact() except AttributeError: # Usamos AttributeError para terminar el thread pass class SyntaxHighliter(QsciScintilla): """ Heredamos de QsciScintilla para detectar la presión de teclas y retornar la línea actual. """ def __init__(self, parent): QsciScintilla.__init__(self, parent) self._output_data = None self._run = True def keyPressEvent(self, event): # Tecla presionada key = event.key() # Posición actual current_pos = self.SendScintilla(self.SCI_GETCURRENTPOS) # Tamaño del contenido length = len(self.text()) # Contenido de la última línea last_line_content = self.text( self.SendScintilla(self.SCI_LINEFROMPOSITION, length) ) # Las teclas arriba, abajo, derecha e izquierda están permitidas if not (key == Qt.Key_Up or key == Qt.Key_Down or key == Qt.Key_Left or key == Qt.Key_Right): # Chequear que se pueda escribir en la posición actual if (length - current_pos - len(last_line_content)) >= 0: return # Tecla enter (más la del teclado numérico) if key == Qt.Key_Enter or key == Qt.Key_Return: # Contenido de la línea actual self._output_data = self.text( self.SendScintilla(self.SCI_LINEFROMPOSITION, length) ) # Llamar a la función original QsciScintilla.keyPressEvent(self, event) def get_input(self): # Esperar hasta que se llene el búfer while self._output_data is None: if not self._run: # Lanzar AttributeError return sleep(0.01) # Remueve el banner ">>> " y convierte los datos output = unicode(self._output_data[4:]) # Resetear el búfer self._output_data = None return output def stop(self): self._run = False class Window(QMainWindow): def __init__(self): # Inicializar la clase padre QMainWindow.__init__(self) # Tamaño y título self.resize(500, 300) self.setWindowTitle("Consola Recursos Python") # Editor - resaltador de sintaxis self.scintilla = SyntaxHighliter(self) self.scintilla.setGeometry(QRect(10, 10, 480, 250)) self.scintilla.setLexer(QsciLexerPython()) # Ejecutar la consola en un nuevo hilo self.console = GUIConsole(self.scintilla) self.console.start() # Ajustar el editor a la ventana self.setCentralWidget(self.scintilla) # Cambiar el output self.original_stdout = sys.stdout sys.stdout = self def write(self, string): self.console.write(string) def closeEvent(self, event): """Terminar el thread y establecer el stdout original""" sys.stdout = self.original_stdout self.scintilla.stop() QMainWindow.closeEvent(self, event) if __name__ == "__main__": app = QApplication([]) window = Window() window.show() app.exec_()
Curso online 👨💻
¡Ya lanzamos el curso oficial de Recursos Python en Udemy!
Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter
en 2024.
Consultoría 💡
Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.