subprocess auf Linux machine

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Hallo,
Ich will ein Programm schreiben mit dem ich auf vier Linux terminals auf einmal zugreifen kann(hab eine Debian Version mit Kernel 3.7). Später dann vielleicht das ich einfach nur eine Zahl eingebe und es erscheinen dann dementsprechend viele Terminals.
Hier ist der code:

Code: Alles auswählen

import subprocess
import sys
from PyQt4 import QtCore, QtGui

def main(argv):
    app = QtGui.QApplication(argv)
    mainwindow = MainWindow()
    mainwindow.show()
    sys.exit(app.exec_())
    
class MainWindow(QtGui.QMainWindow):
  
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.labelHi = QtGui.QLabel("Hi Benutzer")
        self.buttonTestKnopf = QtGui.QPushButton("testknopf")
        #line edits
        self.editLine1 = QtGui.QLineEdit()
        self.editLine2 = QtGui.QLineEdit()
        self.editLine3 = QtGui.QLineEdit()
        self.editLine4 = QtGui.QLineEdit()
        #text edits
        self.editText1 = QtGui.QTextEdit()
        self.editText2 = QtGui.QTextEdit()
        self.editText3 = QtGui.QTextEdit()
        self.editText4 = QtGui.QTextEdit()
        self.setWindowTitle("Shells")
        self.createLayout()
        self.createconnects()
        self.linuxshell()
        
    def createLayout(self):
        widgetZentral = QtGui.QWidget()
        
        layoutZentral = QtGui.QGridLayout()
        layoutZentral.addWidget(self.labelHi, 0, 0)
        #line edits
        layoutZentral.addWidget(self.editLine1, 1, 0)
        layoutZentral.addWidget(self.editLine2, 1, 1)
        layoutZentral.addWidget(self.editLine3, 3, 0)
        layoutZentral.addWidget(self.editLine4, 3, 1)
        #text edits
        layoutZentral.addWidget(self.editText1, 2, 0)
        layoutZentral.addWidget(self.editText2, 2, 1)
        layoutZentral.addWidget(self.editText3, 4, 0)
        layoutZentral.addWidget(self.editText4, 4, 1)
        layoutZentral.addWidget(self.buttonTestKnopf, 5, 0)
        
        
        widgetZentral.setLayout(layoutZentral)
        self.setCentralWidget(widgetZentral)
        
    def createconnects(self):
        self.editLine1.returnPressed.connect(self.editLine1.clear, self.linuxshell())
        self.editLine2.returnPressed.connect(self.editLine2.clear)
        self.editLine3.returnPressed.connect(self.editLine3.clear)
        self.editLine4.returnPressed.connect(self.editLine4.clear)
        
    def linuxshell(self):
        command_input = str(self.editLine1.text())
        subprocess.Popen([command_input], shell=True)
        command_output = subprocess.check_output(command_input)
        self.editText1.setText(command_output)

if __name__ == "__main__":
    main(sys.argv)
Als error bekomme ich:

Code: Alles auswählen

Traceback (most recent call last):
  File "prog.py", line 66, in <module>
    main(sys.argv)
  File "prog.py", line 7, in main
    mainwindow = MainWindow()
  File "prog.py", line 29, in __init__
    self.createconnects()
  File "prog.py", line 54, in createconnects
    self.editLine1.returnPressed.connect(self.editLine1.clear, self.linuxshell())
  File "prog.py", line 62, in linuxshell
    command_output = subprocess.check_output(command_input)
  File "/usr/lib/python2.7/subprocess.py", line 537, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1259, in _execute_child
    raise child_exception
OSError: [Errno 13] Permission denied
:roll:

Kann mir jemand helfen? Ich dachte subprocess.Poppen würde schon allein den stdin, stdout und stderr automatisch zurückliefern, nachdem das command ausgeführt wurde. Ich habs in dem code jetzt erst mal mit einem Fenster versucht. Wenns klappt muss ich es ja einfach für die anderen replizieren. Hab das als root ausgeführt auf dem System(wegen Permission denied, hab keine Ahnung das da schief läuft).

Gruß
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

lies Dir mal die Dokumentation von »subprocess« durch. Die Popen-Zeile führt das Kommando einmal aus, die check_output versucht das gleiche nochmal, da es aber auch eine Liste als Argument erwartet, scheitert es daran, dass es das Kommando "l" oder "c" oder "m", ... nicht versteht.
BlackJack

@JonnyDamnnox: Du rufst die `linuxshell()`-Methode auch viel zu früh auf. Einmal in `createconnects()` wo Du statt dem Aufruf eigentlich nur die Methode selbst übergeben müsstest und dann noch mal am Ende der `__init__()`-Methode. Zu diesem Zeitpunkt steht doch in `textEdit1` sehr wahrscheinlich noch kein sinnvoller Text der ausführbar wäre, oder?

Die Namen sind übrigens grösstenteils zu nichtssagend gewählt. Und wenn man anfängt sie durchzunummerieren ist das ein „code smell” — man möchte dann in aller Regel eigentlich eine Datenstruktur verwenden, meistens eine Liste.

Die Beschreibung im Text passt auch nicht so ganz zum Programm. Das hat mit Terminals nicht viel zu tun. In einem Terminal läuft *dauerhaft* eine Shell. Und so etwas möchte man sich auch nicht selber programmieren, denn das macht mehr Arbeit als es auf den ersten Blick den Anschein hat.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Hallo, danke für die Hilfe
Ich hab jetzt die check Funktion raus gemacht, und dafür Popen eingesetzt.

Code: Alles auswählen

import subprocess
import sys
from PyQt4 import QtCore, QtGui

def main(argv):
    app = QtGui.QApplication(argv)
    mainwindow = MainWindow()
    mainwindow.show()
    sys.exit(app.exec_())
    
class MainWindow(QtGui.QMainWindow):
  
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.labelHi = QtGui.QLabel(self.tr("Hi"))
        self.buttonTestKnopf = QtGui.QPushButton(self.tr("Testknopf"))
        #line edits
        self.editLine1 = QtGui.QLineEdit()
        self.editLine2 = QtGui.QLineEdit()
        self.editLine3 = QtGui.QLineEdit()
        self.editLine4 = QtGui.QLineEdit()
        #text edits
        self.editText1 = QtGui.QTextEdit()
        self.editText2 = QtGui.QTextEdit()
        self.editText3 = QtGui.QTextEdit()
        self.editText4 = QtGui.QTextEdit()
        self.setWindowTitle(self.tr("Hello World"))
        self.createLayout()
        self.createconnects()
        
    def createLayout(self):
        widgetZentral = QtGui.QWidget()
        
        layoutZentral = QtGui.QGridLayout()
        layoutZentral.addWidget(self.labelHi, 0, 0)
        #line edits
        layoutZentral.addWidget(self.editLine1, 1, 0)
        layoutZentral.addWidget(self.editLine2, 1, 1)
        layoutZentral.addWidget(self.editLine3, 3, 0)
        layoutZentral.addWidget(self.editLine4, 3, 1)
        #text edits
        layoutZentral.addWidget(self.editText1, 2, 0)
        layoutZentral.addWidget(self.editText2, 2, 1)
        layoutZentral.addWidget(self.editText3, 4, 0)
        layoutZentral.addWidget(self.editText4, 4, 1)
        layoutZentral.addWidget(self.buttonTestKnopf, 5, 0)
        
        
        widgetZentral.setLayout(layoutZentral)
        self.setCentralWidget(widgetZentral)
        
    def createconnects(self):
        self.editLine1.returnPressed.connect(self.editLine1.clear, self.linuxshell())
        self.editLine2.returnPressed.connect(self.editLine2.clear)
        self.editLine3.returnPressed.connect(self.editLine3.clear)
        self.editLine4.returnPressed.connect(self.editLine4.clear)
        
    def linuxshell(self):
        command_input = str(self.editLine1.text())
        subprocess.Popen([command_input], shell=True)
        proc = subprocess.Popen(command_input, stdout= subprocess.PIPE, shell= True)
        self.editText1.setText(proc.stdout)

if __name__ == "__main__":
    main(sys.argv)
Also jetzt ist der "Permission denied" Fehler weg, jetzt bekomme ich aber "TypeError: QTextEdit.setText(QString): argument 1 has unexpected type 'file'". Das heisst ich könnte es mit :
for line in proc.stdout:
print line

machen. Aber wie krieg ich das als Variable damit ich es schön in self.editText1.setText(blabla) rein kriege? Mit blabla = subprocess.check_call(command_input, stdout=subprocess.PIPE, shell= True) gehts auch nicht, da kommt int error. DIe doc zu subprocess ist leicht kryptisch :x Geht das alles nicht viel einfacher? Hier hat jemand ein Programm mit einer/einem shell/terminal geschrieben, mit os.popen4 :

http://www.saltycrane.com/blog/2007/12/ ... mmand-and/
(Das ist bestimmt auch nicht perfekt, aber ein Anfang wenigstens, irgendwo muss es ja mal anfangen oder?)

Gruß
webspider
User
Beiträge: 485
Registriert: Sonntag 19. Juni 2011, 13:41

Möchte da etwa jemand screen oder tmux nachbauen? Ich hoffe nicht. Ein kurzer Blick in den Code sollte demonstrieren wieviel Aufwand darin investiert wurde.
BlackJack

@JonnyDamnnox: `subprocess` ist eingeführt worden, damit man die ganzen anderen Möglichkeiten externe Programme auszuführen nicht mehr nutzen muss, sondern etwas einheitliches hat. Du musst einfach nur ganz grundlegende Dinge wie Datentypen und Dateien verstehen. Wenn Du den Text aus einer Datei, und das kann jede Datei sein, auch eine Pipe zu einem externen Programm, in einem Widget anzeigen willst, dann musst Du die Datei naheliegenderweise auslesen.

Und Du rufst die Methode immer noch auf statt sie zu übergeben. Die darf nicht vor dem `connect()` aufgerufen werden und dann ihr unsinniger Rückgabewert dann dem `connect()`-Aufruf übergeben werden, sondern Du musst dort *die Methode selbst* übergeben. Ohne Aufruf derselben.

@webspider: Es klang mehr nach einem Terminal, aber das ist nicht weniger aufwändig.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

@BlackJack:

Also ich habs jetzt geändert. Aber was ist eigentlich der Unterschied zwischen, Methode aufrufen und Methode übergeben? Ich denke wenn ich die Methode aufrufe dann erscheint im Argument der Ausgabewert, aber was passiert wenn ich die Funktion einfach nur übergebe?? Oder ist das deswegen weil das Programm warten muss bis ich return gedrück habe, und die Funktion deswegen nicht sofort ausgeführt werden darf? Was ja Sinn macht, weil kein Rückgabewert drin ist.

Code: Alles auswählen

import subprocess
import sys
from PyQt4 import QtCore, QtGui

def main(argv):
    app = QtGui.QApplication(argv)
    mainwindow = MainWindow()
    mainwindow.show()
    sys.exit(app.exec_())
    
class MainWindow(QtGui.QMainWindow):
  
    def __init__(self, *args):
        QtGui.QMainWindow.__init__(self, *args)
        self.labelHalloWelt = QtGui.QLabel(self.tr("Hello World"))
        self.buttonTextAktualisieren = QtGui.QPushButton(self.tr("Update"))
        #line edits
        self.editLine1 = QtGui.QLineEdit()
        self.editLine2 = QtGui.QLineEdit()
        self.editLine3 = QtGui.QLineEdit()
        self.editLine4 = QtGui.QLineEdit()
        #text edits
        self.editText1 = QtGui.QTextEdit()
        self.editText2 = QtGui.QTextEdit()
        self.editText3 = QtGui.QTextEdit()
        self.editText4 = QtGui.QTextEdit()
        self.setWindowTitle(self.tr("Hello World"))
        self.createLayout()
        self.createconnects()
        
    def createLayout(self):
        widgetZentral = QtGui.QWidget()
        
        layoutZentral = QtGui.QGridLayout()
        layoutZentral.addWidget(self.labelHalloWelt, 0, 0)
        #line edits
        layoutZentral.addWidget(self.editLine1, 1, 0)
        layoutZentral.addWidget(self.editLine2, 1, 1)
        layoutZentral.addWidget(self.editLine3, 3, 0)
        layoutZentral.addWidget(self.editLine4, 3, 1)
        #text edits
        layoutZentral.addWidget(self.editText1, 2, 0)
        layoutZentral.addWidget(self.editText2, 2, 1)
        layoutZentral.addWidget(self.editText3, 4, 0)
        layoutZentral.addWidget(self.editText4, 4, 1)
        layoutZentral.addWidget(self.buttonTextAktualisieren, 5, 0)
        
        
        widgetZentral.setLayout(layoutZentral)
        self.setCentralWidget(widgetZentral)
        
    def createconnects(self):
        self.editLine1.returnPressed.connect(self.editLine1.clear, self.linuxshell)
        self.editLine2.returnPressed.connect(self.editLine2.clear)
        self.editLine3.returnPressed.connect(self.editLine3.clear)
        self.editLine4.returnPressed.connect(self.editLine4.clear)
        
    def linuxshell(self):
        command_input = str(self.editLine1.text())
        subprocess.Popen(command_input, shell=True)
        proc = subprocess.Popen(command_input, stdout= subprocess.PIPE, shell=True)
        out = proc.stdout.readline()
        self.editText1.setText(out)

if __name__ == "__main__":
    main(sys.argv)
Das ist jetzt wieder der neue code. Diesmal mit readline() , das sollte dann die pipe auslesen. Als error kommt aber das das Argument ein Qt.ConnectionType sein soll. Die Erklärung bei PySideDoc sagt mir leider nicht viel. Kann mir das jemand erklären?

Gruß
BlackJack

@JonnyDamnnox: Man muss die Methode übergeben weil Qt die aufrufen soll wenn man Enter betätigt.

Die Ausnahme bekommst Du weil `connect()` als zweites Argument eben genau das erwartet was die Fehlermeldung sagt. Wie bist Du überhaupt auf die Idee gekommen man könnte einfach so zwei Slots/Empfänger als Argumente übergeben? Es geht nur ein Slot/Empfänger pro `connect()`-Aufruf.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@JonnyDamnnox: Funktionen / Methoden / Klassen sind in Python halt auch noch mal für sich eigene Objekte. Also der ganze Block, der unterhalb deines `def xyz()` steht, ist der Code (sog. Rumpf) für die jeweilige Funktion. Dieser Block wird an PyQt übergeben, aber in dem Moment noch nicht ausgeführt. Stell es dir so vor als wenn du jemandem eine Maschine übergibst und derjenige muss bzw soll sie von sich aus starten, um ein bestimmtes Ergebnis zu erhalten. Erst ein `()` sorgt dafür, dass ein ausführbarer Block auch tatsächlich ausgeführt wird. Vorher ist es einfach nur ein Funktionsobjekt.

Und das Signal-Slot-Konzept beruht eben darauf, dass man nur ausführbare Objekte übergibt. Die tatsächliche Ausführung soll erst dann geschehen, wenn ein bestimmtes Ereignis (z.B. Klick auf Button) eingetreten ist. Wenn du etwas schon bei der Übergabe ausführst (also Klammern benutzt), dann überreichst du ja nur die Rückgabe der Funktion, nicht aber die Funktion an sich. Hoffe, es ist jetzt etwas klarer für dich geworden.

EDIT: Und ja, man übergibt nicht wirklich Codeblöcke, sondern im Endeffekt als Funktionsobjekt vorkompilierten Bytecode. Solche technischen Details wollte ich für einen Anfänger jetzt erstmal außen vorlassen.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

@BlackJack:
Frag lieber nicht :roll: , ich sag nur so viel, Ignoranz und Dummheit haben dabei eine Rolle gespielt.
@snafu:
Ok danke, dass war mir immer ein Rätsel. Aber es macht ja auch Sinn !

Jedenfalls wird jetzt der output angezeigt.

Code: Alles auswählen

.....
    def createconnects(self):
        self.editLine1.returnPressed.connect(self.linuxshell)
        self.editLine2.returnPressed.connect(self.editLine2.clear)
        self.editLine3.returnPressed.connect(self.editLine3.clear)
        self.editLine4.returnPressed.connect(self.editLine4.clear)
        
    def linuxshell(self):
        command_input = str(self.editLine1.text())
        output = Popen(command_input, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT,    close_fds=True)
        finished_output = output.stdout.read()
        self.editText1.setText(finished_output)
.....
Allerdings funktioniert ausser den output anschauen nix. Also keine laufenden Prozesse, oder Verzeichniswechself geht auch nicht. Der output müsste auch immer geupdated werden wenn was neues passiert(geht bestimmt mit einer while-Schleife?) Andere Befehle gehen auch nicht(z.B. mkdir oder so). Kann mir jetzt noch jemand einen Tipp geben wie ich es hinbekomme das auf den Terminals dann flüssig Prozesse ablaufen? Z.b. einen commandline editor, oder einen server starten. Bleibt nämlich hängen. Ich hab schon nach multithreading geschaut, mit thread und start_new_thread sieht das eigentlich ganz einfach aus. Aber ich bin nicht sicher ob das das richtige ist und wo ich das dann hinplatzieren soll. Vielleicht ein paar Tipps in die richtige Richtung :) ?

Gruß
BlackJack

@JonnyDamnnox: Du müsstest halt nicht immer neue Shells starten, denn ``cd`` funktioniert schon, aber halt nur in der Shell die danach gleich wieder beendet wird. Und das hat keine Auswirkung auf die Shell die für die nächste Eingabe gestartet wird.

Du müsstest eine Shell dauerhaft starten und der vorgaukeln sie würde in einem Terminal laufen, und regelmässig deren Ausgabe auf ihrer Standardausgabe und der Standardfehlerausgabe verarbeiten und anzeigen und dabei vielleicht auch noch Terminal-Escape-Sequenzen interpretieren und umsetzen. Das ist alles nicht wirklich trivial. Warum willst Du dass denn überhaupt machen? Es gibt doch schon Terminals wie Sand am Meer.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

@BlackJack:

Ja weil ich meistens mehrere terminals brauche wenn ich irgendwas in Linux mache. Und ich dachte da könnte ich mit Python mal etwas sinnvolles(ausser "Wer wird Millionär" Programme) programmieren. Ok ich könnte vier einzelne Terminals öffnen und dann auf dem Bildschirm hin und her schieben, aber das ist nicht so komfortabel wie meine Idee.
Naja vielleicht finde ich noch etwas nützliches bei google :|

Gruß
BlackJack

@JonnyDamnnox: Wie gesagt, es gibt Terminals wie Sand am Meer. Das KDE-Standard-Terminal Konsole kann man zum Beispiel splitten. Macht man zweimal, einmal horizontal und einmal vertikal, und schon hat man ein Fenster mit vier Terminals.
Benutzeravatar
snafu
User
Beiträge: 6741
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn man mehrere Terminals in einem gemeinsamen Fenster haben möchte, könnte man alternativ auch Terminator benutzten. Der ist sogar in Python geschrieben.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Ging doch etwas einfacher :D

Es gib für GTK+3 eine sogenannte Vte(Virtual terminal emulator schätze ich mal) library :

http://packages.debian.org/wheezy/gir1.2-vte-2.90
https://developer.gnome.org/vte/0.26/VteTerminal.html

Und dafür gibt es auch python-bindings. Das Programm und Programmcode sieht zwar noch scheisse aus und man könnte auch das layout besser machen(am Anfang wird die Eingabe vom Fenster verdeckt und verzieht), und ein paar Sachen hab ich auch noch nicht ganz verstanden(was vte betrifft). Aber es funktioniert genau so wie ich es mir vorgestellt habe. Ich nenne es "shells" oder so....

Code: Alles auswählen

#!usr/bin/env python

from gi.repository import Gtk, Vte, Gdk
from gi.repository import GLib
import os

class MainWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="shells")
        self.resize(800, 600)

        table = Gtk.Table(2, 2, True)
        self.add(table)
        palette = [Gdk.color_parse('red')] * 16
        terminal1 = Vte.Terminal()
        terminal2 = Vte.Terminal()
        terminal3 = Vte.Terminal()
        terminal4 = Vte.Terminal()
        #terminal1.connect('decrease-font-size', self.main_quit() )
        
        scrolledwindow1 = Gtk.ScrolledWindow()
        scrolledwindow1.add(terminal1)
        
        scrolledwindow2 = Gtk.ScrolledWindow()
        scrolledwindow2.add(terminal2)
        
        scrolledwindow3 = Gtk.ScrolledWindow()
        scrolledwindow3.add(terminal3)
        
        scrolledwindow4 = Gtk.ScrolledWindow()
        scrolledwindow4.add(terminal4)
        
        terminal1.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                       [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal2.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"],
                                       [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal3.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"],
                                       [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal4.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"],
                                       [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
                                       
        terminal1.set_colors(Gdk.color_parse('red'), Gdk.color_parse('black'), palette)
        terminal2.set_colors(Gdk.color_parse('green'), Gdk.color_parse('black'), palette)
        terminal3.set_colors(Gdk.color_parse('yellow'), Gdk.color_parse('black'), palette)
        terminal4.set_colors(Gdk.color_parse('blue'), Gdk.color_parse('black'), palette)
        
        table.attach(scrolledwindow1, 0, 1, 0, 1)
        table.attach(scrolledwindow2, 1, 2, 0, 1)
        table.attach(scrolledwindow3, 0, 1, 1, 2)
        table.attach(scrolledwindow4, 1, 2, 1, 2)
        
win = MainWindow()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
Habe es noch nicht langzeit getestet. Exit funktioniert auch nicht(friert ein). Die Schrift würde ich auch gern noch verkleinern, geht auch mit einem Signal über das normale crtl - irgendwie. aber ich denk mal das es schon gut zu gebrauchen ist. Mit vte kann man noch einiges mehr machen, aber leider ist die doc für den Arsch. Die shell muss standartmäßig in bin/sh installiert sein, und home als Standartverzeichniss, aber kann ja jeder ändern wie er will.

Gruß
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Jetzt kann man auch einfach die Schriftgröße und font ändern ;)

Code: Alles auswählen

#!/usr/bin/env python

import os
from gi.repository import GLib
from gi.repository import Pango
from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import Vte

class MainWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="shells")
        self.resize(1000, 1000)

        table = Gtk.Table(2, 2, True)
        fonte = Pango.FontDescription("Purisa 7")
        
        self.add(table)
        
        palette = [Gdk.color_parse('red')] * 16
        terminal1 = Vte.Terminal()
        terminal1.connect('realize', self.on_realize_terminal)
        
        terminal2 = Vte.Terminal()
        terminal2.connect('realize', self.on_realize_terminal)
        
        terminal3 = Vte.Terminal()
        terminal3.connect('realize', self.on_realize_terminal)
        
        terminal4 = Vte.Terminal()
        terminal4.connect('realize', self.on_realize_terminal)
        
        terminal1.set_font(fonte)
        terminal2.set_font(fonte)
        terminal3.set_font(fonte)
        terminal4.set_font(fonte)
        
        scrolledwindow1 = Gtk.ScrolledWindow()
        scrolledwindow1.add(terminal1)
        scrolledwindow2 = Gtk.ScrolledWindow()
        scrolledwindow2.add(terminal2)
        scrolledwindow3 = Gtk.ScrolledWindow()
        scrolledwindow3.add(terminal3)
        scrolledwindow4 = Gtk.ScrolledWindow()
        scrolledwindow4.add(terminal4)

        terminal1.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                   [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal2.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                   [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal3.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                   [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
        terminal4.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                   [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
                                   
        terminal1.set_colors(Gdk.color_parse('red'), Gdk.color_parse('black'), palette)
        terminal2.set_colors(Gdk.color_parse('green'), Gdk.color_parse('black'), palette)
        terminal3.set_colors(Gdk.color_parse('blue'), Gdk.color_parse('black'), palette)
        terminal4.set_colors(Gdk.color_parse('yellow'), Gdk.color_parse('black'), palette)
       
        table.attach(scrolledwindow1, 0, 1, 0, 1)
        table.attach(scrolledwindow2, 1, 2, 0, 1)
        table.attach(scrolledwindow3, 0, 1, 1, 2)
        table.attach(scrolledwindow4, 1, 2, 1, 2)

    def on_realize_terminal(self, terminal):
        font = terminal.get_font()
        


if __name__ == '__main__':
    win = MainWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()

EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du hast da noch viel zu viel doppelten Code:

Code: Alles auswählen

from gi.repository import GLib
from gi.repository import Pango
from gi.repository import Gdk
from gi.repository import Gtk
from gi.repository import Vte

class MainWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="shells")
        self.resize(1000, 1000)

        table = Gtk.Table(2, 2, True)
        fonte = Pango.FontDescription("Purisa 7")
        
        self.add(table)
        
        palette = [Gdk.color_parse('red')] * 16

        for color, xs in (("red", (0, 1, 0, 1)),
                          ("green", (1, 2, 0, 1)),
                          ("blue", (0, 1, 1, 2)),
                          ("yellow", (1, 2, 1, 2))):
            terminal = Vte.Terminal()
            terminal.connect('realize', self.on_realize_terminal)
            
            terminal.set_font(fonte)
            
            scrolledwindow = Gtk.ScrolledWindow()
            scrolledwindow.add(terminal)

            terminal.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/sh"], 
                                    [], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
                                    
            terminal.set_colors(Gdk.color_parse(color), Gdk.color_parse('black'), palette)
        
            table.attach(scrolledwindow, *xs)

    def on_realize_terminal(self, terminal):
        font = terminal.get_font()
        

if __name__ == '__main__':
    win = MainWindow()
    win.connect("delete-event", Gtk.main_quit)
    win.show_all()
    Gtk.main()
Das Leben ist wie ein Tennisball.
JonnyDamnnox
User
Beiträge: 68
Registriert: Sonntag 10. März 2013, 21:14

Hey danke : -)

Gruß
Antworten