I am trying to develop a "console" in pyqt. Similar to xterm.js where all the console is, is front end it does not spawn any sub-processes its just an I/O for me to plug in whatever I want to at a later date.
are there any existing python packages or simple widgets I can use that would allow me to put a terminal like interface within my pyqt application?
its a client server application so the terminal is used to send commands to the backend server and retrieve output as if it were a bash shell (for example)
You can use QTermWidget (if you can't install it and you're using ubuntu then you can check this answer).
For example a translation of the official RemoteTerm example that allows to access the shell remotely through sockets would be the following:
terminal.py
import os
import sys
from PyQt5 import QtCore, QtWidgets, QtNetwork
import QTermWidget
class RemoteTerm(QTermWidget.QTermWidget):
def __init__(self, ipaddr, port, parent=None):
super().__init__(0, parent)
self.socket = QtNetwork.QTcpSocket(self)
self.socket.error.connect(self.atError)
self.socket.readyRead.connect(self.on_readyRead)
self.sendData.connect(self.socket.write)
self.startTerminalTeletype()
self.socket.connectToHost(ipaddr, port)
@QtCore.pyqtSlot()
def on_readyRead(self):
data = self.socket.readAll().data()
os.write(self.getPtySlaveFd(), data)
@QtCore.pyqtSlot()
def atError(self):
print(self.socket.errorString())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
QtCore.QCoreApplication.setApplicationName("QTermWidget Test")
QtCore.QCoreApplication.setApplicationVersion("1.0")
parser = QtCore.QCommandLineParser()
parser.addHelpOption()
parser.addVersionOption()
parser.setApplicationDescription(
"Example(client-side) for remote terminal of QTermWidget"
)
parser.addPositionalArgument("ipaddr", "adrress of host")
parser.addPositionalArgument("port", "port of host")
parser.process(QtCore.QCoreApplication.arguments())
requiredArguments = parser.positionalArguments()
if len(requiredArguments) != 2:
parser.showHelp(1)
sys.exit(-1)
address, port = requiredArguments
w = RemoteTerm(QtNetwork.QHostAddress(address), int(port))
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
shell-srv.py
#!/usr/bin/env python
import sys
import os
import socket
import pty
def usage(program):
print("Example(server-side) for remote terminal of QTermWidget.")
print("Usage: %s ipaddr port" % program)
def main():
if len(sys.argv) != 3:
usage(sys.argv[0])
sys.exit(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((sys.argv[1], int(sys.argv[2])))
s.listen(0)
print("[+]Start Server.")
except Exception as e:
print("[-]Error Happened: %s" % e.message)
sys.exit(2)
while True:
c = s.accept()
os.dup2(c[0].fileno(), 0)
os.dup2(c[0].fileno(), 1)
os.dup2(c[0].fileno(), 2)
# It's important to use pty to spawn the shell.
pty.spawn("/bin/sh")
c[0].close()
if __name__ == "__main__":
main()