Konsole in GUI- Fenster

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Hi,
ich habe ein Konsolen-Programm geschrieben. Um jetzt nach und nach einzelne Teile Buttons grafisch darzustellen brauche ich z.B. TKInter (ist mir klar). Aber für den Anfang würde ich gerne eine " virtuelle Konsole" in einem Hauptfenster haben, und dann nach und nach einige Auswahlfunktionen über Buttons ersetzen, aber den Hauptteil wie: print und raw_input in der "virtuellen" Konsole laufen lassen.

ist so etwas einfach möglich oder sollte ich umdenken?
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Hi mathi,
du kannst einfach mit dem os-modul deine Ein- und Ausgaben umleiten.
Bsp:

Code: Alles auswählen

import Tkinter as tk
import sys
class TkConsole:
    def __init__(self):
        self.console= tk.Text(width=80, height=20)
        self.console.pack()
    def write(self, text):
        self.console.insert("end", text)

c = TkConsole()
sys.stdout = c
print "Ich bin ein Testingteststring"
tk.mainloop()
sys.stdout kanns du ein beliebiges Objekt mit einer "write"-Methode übergeben. Ähnlich gehts mit sys.stdin und sys.stderr.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

vielen Dank, das war im Grunde was ich suche, mit dem kleinen Problem, das ich keine Interaktion habe:

Code: Alles auswählen

# -*- coding: cp1252 -*-
import Tkinter as tk 
import sys 
class TkConsole: 
    def __init__(self): 
        self.console= tk.Text(width=80, height=20) 
        self.console.pack() 
    def write(self, text): 
        self.console.insert("end", text) 
c = TkConsole() 
sys.stdout = c 
print "Ich bin ein Testingteststring" 

p=eval(raw_input("Eingabewert= "))
a=3
b=5
c=a+b
print 'p=%0.2f' % p
print c 
f=open("foo.txt","w") # öffne upatemodus
f.write ("test2")
f.close()
tk.mainloop()
--- ich hoffe ich habe mich verständlich machen können---
ich möchte halt mit raw_input werte empfangen und weiterverarbeiten.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Unter PyGTK gibt es dafür VTE.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Wie kann ich das unter Windows schaffen ?? :?:

Wichtig ist mir, dass ich dann mit pyinstaller eine .exe erstellen kann, die auch an Fremdrechnern lauffähig ist.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Hi mathi.

Du kannst dir das raw_input sparen wenn du deine Eingabeaufforderung mit eval() interpretierst, da hast du nichts anderes als ein input().

Code: Alles auswählen

C:\>python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> p=eval(raw_input("Eingabbewert= "))
Eingabbewert= sys.exit(0)

C:\>
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@Zap

eval(raw_input()) bedeutet dass ich einen String einlese mit raw_input und diesen dann als Zahl interpretiere (aus Sicherheitsgründen) - so raten es einige hier im Forum und ich finde das plausibel :D

hilft mir das ´bei meinem Problem? Begreife ich leider nicht :oops:
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Sorry das ich dir bei deinem eigentlichen Problem nicht helfen kann, da ich weder ausreichen TK erfahrung hab und auch für andere GUI Frameworks gerade keine Lösung parat hab.

Ich wollte dich nur darauf aufmerksam machen das deine Syntax meiner Meinung nach nicht sicherer ist als ein normales input() weil du auch jeden String als code interpretierst.
Guck dir mal meinen Log oben genauer an, dann weißt du was ich meine.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@Zap
Im Grunde hättest Du recht.
Ich habe es bis jetzt so gemacht:

-wenn eine zahl erwartet wird: eval(raw_input())
-wenn ein String erwartet wird: raw_input()
CM hat geschrieben:Nein, natürlich nicht. Aber input() hat so seine Haken:

Code: Alles auswählen

input(...)
    input([prompt]) -> value
    
    Equivalent to eval(raw_input(prompt)).
D. h. für Dich, wenn Du wirklich nichts Anderes machen willst, ist das ok. Aber sonst kannst Du Dir Sicherheitslücken einbauen.

Gruß,
Christian
BlackJack hat geschrieben:Sicherheit ist immer ein Problem wenn man sich erst einmal an `input()` gewöhnt weil's so schön einfach ist, hat man das früher oder später auch in wichtigem Quelltext oder es gelangt per copy'n'paste aus "unwichtigem" Quelltext in ein wichtiges Programm.

Ab Python 3.0 verhält sich `input()` dann auch wie `raw_input()`, da kann man also jetzt schon den sauberen Weg lernen und verwenden.
@all
Aber back to topic:

Hat keiner eine idee: Ich kann leider mit folgender Lösung nur wenig anfangen, obwohl das doch genau das richtige zu sein scheint:
http://www.python-forum.de/topic-7566.h ... tin+thurau
BlackJack

Doch noch einmal zum `eval()`: Damit wandelst Du die Zeichenkette nicht in eine Zahl um ─ sie wird als Python-Quelltext angesehen und ausgeführt. Egal welchen Quelltext man da eingibt; also letztlich genau das gleiche was `input()` macht. Zahlen kommen da nur zufällig heraus, wenn die Eingabe auch wirklich eine Zahl war.

Um eine Zeichenkette in eine Zahl um zu wandeln, und auch *nur* das, muss man `int()` oder `float()` anstelle von `eval()` verwenden, je nach dem was für einen Typ man haben möchte.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

ok habe ich begriffen und geändert:

Code: Alles auswählen

 p=float(raw_input("Eingabewert= "))

Mein Problem mit der Konsole bleibt aber :cry:
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

keiner eine Idee bzw. Hilfe??
BlackJack

Das "einfachste" wäre es wahrscheinlich so eine "Konsole" aus einem `Text`-Widget für die Ausgaben und einem `Entry` für die Eingaben zu programmieren, und das über Sockets mit Deinem ``print``/`raw_input()` verwendenden Quelltext so zu verbinden, dass `sys.stdin` und `sys.stdout` mit dieser Konsole verbunden sind.

Das Hauptproblem ist, dass bei ``print``/`rawinput()` Dein Programm die zeitliche Abfolge bestimmt, GUIs aber ereignisbasiert sind, d.h. der Anwender letztendlich bestimmt wann welcher Code ausgeführt wird. Beides zu mischen verträgt sich nicht so besonders gut.

Oder Du ersetzt `raw_input()` durch eine Funktion die jedesmal ein Fenster mit dem Prompt und einem Entry aufmacht. Das ist zwar einfacher, aber für den Benutzer eine ziemlich lästige GUI.

Im Idealfall hast Du beim bisherigen Quelltext Anwendungslogik und UI voneinander getrennt. Dann kannst Du Deine GUI Stück für Stück aufbauen. Es ist zwar dann erst zum Schluss der ganze Funktionsumfang verfügbar, aber es gibt immer eine funktionierende Teilmenge davon.
Benutzeravatar
nkoehring
User
Beiträge: 543
Registriert: Mittwoch 7. Februar 2007, 17:37
Wohnort: naehe Halle/Saale
Kontaktdaten:

mathi hat geschrieben:ok habe ich begriffen und geändert:

Code: Alles auswählen

 p=float(raw_input("Eingabewert= "))
Ich will dir noch nen Tipp dazu in Form eines kleinen Auszugs geben:

Code: Alles auswählen

In [9]: float("bla")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

D:\Eigene Dateien\devel\<ipython console> in <module>()

ValueError: invalid literal for float(): bla
Du solltest also nicht einfach so umwandeln. Machs lieber ungefaehr so:

Code: Alles auswählen

while True:
    value = raw_input("Eingabewert? ")
    try:
        value = float(value)
        break
    except ValueError:
        print "Na das ist aber keine Zahl!"
Das wirkt jetzt vielleicht alles total umstaendlich gegenueber der eval- oder input-Variante, aber Programmabstuerze aus Faulheit des Programmierers bringen dem User nicht viel Freude ;)


mathi hat geschrieben:Mein Problem mit der Konsole bleibt aber :cry:
Sorry for that :oops:
[url=http://www.python-forum.de/post-86552.html]~ Wahnsinn ist auch nur eine andere Form der Intelligenz ~[/url]
hackerkey://v4sw6CYUShw5pr7Uck3ma3/4u7LNw2/3TXGm5l6+GSOarch/i2e6+t2b9GOen7g5RAPa2XsMr2
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

@nkoehring:

hossa, das bringt bei 50 Eingabeabfragen auch 50 while-Schleifen richtig??

hmmm :shock:

@BlackJack:

das hört sich für mich kompliziert an, da ich erst seit 2 Monaten überhaupt programmiere. Ich glaube ich muß das lassen und auf konsole bleiben.
BlackJack

Wenn die 50 ``while``-Schleifen alle fast gleich aussehen schreibt man natürlich eine Funktion dafür.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Code: Alles auswählen

def floatx(value):
    try:
        value = float(value)
        return value
        break
    except ValueError: 
        print "Na das ist aber keine Zahl!"
    

while True: 
    eingabe = raw_input("Eingabewert? ") 
    ausgabe=floatx(eingabe)

print ausgabe

Warum funktioniert das nicht? --> Fehler: break in Loop??
BlackJack

Das ``break`` steht nicht in einer Schleife. Es würde allerdings sowieso nie ausgeführt, weil das ``return`` in der Zeile darüber den Ablauf der Funktion ja schon abbricht.

Allerdings hättest Du auf diese Weise immer noch 50 ``while``-Schleifen. Die Schleife sollte man mit in die Funktion stecken. Die 50 Aufrufe sollten dann ungefähr so aussehen:

Code: Alles auswählen

wert = float_input('Eingabewert? ')
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

Das verstehe ich nicht.

jeder Eingabewert hat einen anderen Namen und wird durch einen anderen string hinter raw_input beschrieben.
-> (konntest Du nicht wissen)

Deshalb dachte ich an die obige Lösung, wenn aber die Schleife in der Funktion steckt, müßte auch die Eingabe in der Funktion sein, oder?
Also doch 50 Schleifen? :cry:
BlackJack

Okay, Aufruf der neuen Funktion für zwei verschiedene Werte:

Code: Alles auswählen

radius = float_input('Bitte den Radius eingeben: ')
hoehe = float_input('Und die Hoehe: ')
Zwei Werte die an verschiedene Namen gebunden werden, mit einer eigenen Zeichenkette als Prompt. In der `float_input()` ist weiterhin nur *eine* Schleife.
Antworten