Python Texteditor

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.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

deets hat geschrieben:Und das while True ist warum da?
Vielleicht möchte er nur die Götter beschwören, dass sie doch endlich wieder Ladung aus großen Vögeln abwerfen :D
Nobuddy hat geschrieben:Vielleicht habe ich da mal was falsch verstanden. Dachte es wäre immer gut, eine bestimmte Situation mit break zu beenden. Ist das falsch?
Und warum glaubst du, dass das gut sein soll? Hier ist die Schleife doch offensichtlich total unnötig.
Das Leben ist wie ein Tennisball.
deets

Nobuddy hat geschrieben:
deets hat geschrieben:Und das while True ist warum da? Wo du doch eh dauernd raus-breakst? Und warum printed eine solche Funktion eine Fehlermeldung anstatt eine Exception zu schmeissen, mit der du im umgebenden Code etwas anfangen kannst, statt einfach so zu tun, als ob alles ok gewesen waere?
Vielleicht habe ich da mal was falsch verstanden. Dachte es wäre immer gut, eine bestimmte Situation mit break zu beenden. Ist das falsch?
Das mit der Exception, ist eine gute Idee, werde das ändern.
Man benutzt break, wenn man es braucht, um aus einer Schleife auszubrechen. Und eine Schleife braucht man, wenn man Code mehr als einmal laufen lassen will. Brauchst du in deinem gezeigten Code eine Schleife? Nein. Also brauchst du auch kein break. Du kannst natuerlich auch so progammieren:

Code: Alles auswählen

while True:
    while True:
         while True:
              print "einmal ausgefuehrt"
              break
         break
     break
Aber warum sollte man sowas machen?
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Da habe ich wohl wieder einen Treffer gelandet ... :lol:
Sorry, Ihr habt Recht, ändere es entsprechend.

Das mit der Exception, ist mir allerdings im nach hinein nicht klar.
Im ersten Teil überprüfe ich ja nur, welches der mir bekannten Betriebsystemen hier läuft.
Anschließend weise ich den Betriebsystemen, eine Variable mit dem spezifischen Befehl zum Starten des Standardprogrmmes zu.
Ich bekomme keine Exception so zu Stande.
Wie kann ich das mit der Exception bewerkstelligen?
deets

Bitte arbeite ein Tutorial zum Thema Exceptions durch und stell dann konkrete Fragen. Dir jetzt hier saemtliche Konstrukte von Python vorzukauen ist ein bisschen viel.
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Vergiss das Thema Exception, habe es gelöst.

Code: Alles auswählen

def sysprog(filename):
    # Betriebssytem ermitteln und Datei mit Standardprogramm öffnen.
    linux = sys.platform.startswith('lin')
    osx = sys.platform.startswith('os')
    windows = sys.platform.startswith('win')
    text = ('Datei %s wird mit dem Standardprogramm\nIhres Betriebsystem zum Editieren geöffnet!' % filename)
    if linux:
        standardedit = 'xdg-open'
        print(text)
    elif osx:
        standardedit = 'open'
        print(text)
    elif windows:
        # standardedit = 'os.startfile'
        standardedit = 'start'
        print(text)
    try:
        process = subprocess.Popen([standardedit, filename])
        process.wait()
    except UnboundLocalError:
        print('Sie arbeiten mit dem Betriebssystem %s.' % sys.platform)
        print('Das Standardprogramm zum Starten von %s, ist nicht bekannt.\n' % filename)
        print('Öffnen Sie die Datei %s zum Editieren mit einem Texteditor.' % filename)
        print('Die Datei %s befindet sich unter\n%s.' % (filename, os.path.realpath(filename)))
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du hast wirlich ein Händchen dafür, die schlechtesten aller verfügbaren Ansätze umzusetzen ^^ Generell kann man sagen, dass das Abfangen eines UnboundLocalError keine gute Idee ist, da dies der perfekte Ort ist, um sich richtig schöne Fehler in das Programm zu bauen. Stell dir mal vor, du hättest "filename" in dem try-Block verkehrt geschrieben oder, was noch viel schlimmer ist, du rufst im try-Block eine Funkion auf, welche einen UnboundLocalError wirft. Damit hast du dir dann im Prinzip das Debughorrszenario geschaffen.

Weiter kommt hinzu, dass du in jedem if/elif-Block den Text ausgist. Wir haben dich schon mehrfach darauf hingewiesen, dass man Code nicht kopiert. Das kann man doch problemlos zusammenfassen. Natürlich vermischt du auch wieder Ausgabe und Logik.

Nun zu deinem eigentlichen Problem: deets hat dich doch darauf hingewiesen, dass Ausgaben von Fehlermeldungen keine ausreichende Fehlerbehandlung sind. Wenn du so mit Fehlern umgehst, wird eine Meldung ausgegeben und dann Programm einfach irgendwo mit einer Ausnahme crashen oder im schlimmsten Fall einfach undefiniert weiterlaufen. Das kann natürlich nur zu interessantem Verhalten und unmöglich zu debuggendem Code führen. Du sollst hier keine Exception abfangen, sondern deine eigene Exception werfen, wenn du kein Programm zum öffnen finden konntest. Dein Programm kann dann an geeigneter stelle diese Ausnahme behandeln und deterministisch darauf reagieren. Bei dir kann man nur hoffen und beten, dass in einem Fehlerfall nichts kaputt geht.
Das Leben ist wie ein Tennisball.
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Ich war mir eigentlich sicher, hier den richtigen Ansatz zu haben.
Schreibfehler sind immer ein Risiko, welches man aber beim Schreiben und Testen vom Code feststellen kann.

Ausgaben von Fehlermeldungen keine ausreichende Fehlerbehandlung, das ist richtig aber für jemand der dann das Programm nutzt, zumindest eine verständliche Info.

Vielleicht könntet Ihr mir in kurzen Zügen zeigen, wie es richtig wäre?
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Ganz grob, auch das könnte man besser trennen, aber ich wollte mich an deinem Code halten (ungetestet, und im Browser eingerückt ;-) ).

Code: Alles auswählen

def sysprog():
     # Betriebssytem ermitteln und Datei mit Standardprogramm öffnen.
     linux = sys.platform.startswith('lin')
     osx = sys.platform.startswith('os')
     windows = sys.platform.startswith('win')
     if linux:
         standardedit = 'xdg-open'
     elif osx:
         standardedit = 'open'
     elif windows:
         standardedit = 'start'
     else:
         raise RuntimeError("Konnte Betriebsystem nicht herraus finden")
     return standardedit

def fileopen(filename):
    try:
         default_program = sysprog()
    except RuntimeError, e:
        print(e)
    else:
        print('Datei %s wird mit dem Standardprogramm\nIhres Betriebsystem zum Editieren geöffnet!' % filename)
        process = subprocess.Popen([default_program, filename])
        process.wait()
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Hallo Sr4l,
Danke für Deinen Input, der Code sieht gut aus, wäre aber da drauf nicht gekommen.
Aber jetzt habe ich wieder etwas dazu gelernt. :wink:

Einziger Schönheitsfehler ist hier

Code: Alles auswählen

except RuntimeError, e:
dies funktioniert bei mir nur mit

Code: Alles auswählen

except RuntimeError as e:
An sonst funktioniert der Code von Dir prima, Danke!

Da hab ich noch eine Menge zu lernen und hoffe auch auf Eure zukünftige Unterstützung. :wink:
Malachite
User
Beiträge: 34
Registriert: Sonntag 24. Juni 2012, 13:43
Wohnort: Berlin

Noch was zu xdg-open: Es ist nicht nur auf Linux, sondern auf den meisten unixoiden Systemen installiert (bei Solaris und manchen Linux-Distributionen muss man xdg-utils nachinstallieren), daher würde ich es folgendermaßen schreiben, denn wenn ein Programm nicht unter Windows läuft, ist davon auszugehen, dass es auf einem unixoiden System läuft:

Code: Alles auswählen

if os.platform.startswith('win'):
    startcmd = 'start' # standardedit trifft hier ja nicht mehr zu…
elif os.platform.startswith('darwin'): # und nicht 'os' ;)
    startcmd = 'open'
else:
    startcmd = 'xdg-open'
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Hallo Malachite,
Dein Code verkürzt das Ganze nochmal auf das Wesentliche.
Daß xdg-open auf den meisten unixoiden Systemen installiert ist, kann schon sein.
Aber auf eine Exception kann jedoch nicht verzichtet werden.

Der Code mit der Exception sollte so richtig sein, bin mir aber nicht ganz sicher.

Code: Alles auswählen

def sysprog():
     # Betriebssytem ermitteln und Datei mit Standardprogramm öffnen.
    if sys.platform.startswith('win'):
        startcmd = 'start'
    elif sys.platform.startswith('darwin'):
        startcmd = 'open'
    else:
        try:
            startcmd = 'xdg-open'
        except:
            raise RuntimeError("Konnte Betriebsystem nicht herraus finden")
    return startcmd
Wäre das so ok?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wie soll das denn funktionieren? Es gibt doch überhaupt keine Möglichkeit, dass das raise jemals erreicht wird. Hast du mal ein Tutorial zu Exceptions durchgearbeitet? Und warum testest du deinen Code nicht, dann wäre dir sofort aufgefallen, dass der Code nicht funktioniert.
Das Leben ist wie ein Tennisball.
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

@EyDu, ich arbeite das Tutorial zu Exceptions durch, Danke für den Hinweis. :wink:
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Wie ich es mit obiger Konstellation und der Exception gehen soll, konnte ich noch keine Lösung finden.

Ich habe den Code jetzt so abgeändert, daß es keine probleme gibt.

Code: Alles auswählen

def sysprog():
     # Betriebssytem ermitteln und Datei mit Standardprogramm öffnen.
    if sys.platform.startswith('lin'):
        startcmd = 'xdg-open'
    elif sys.platform.startswith('darwin'):
        startcmd = 'open'
    elif sys.platform.startswith('win'):
        startcmd = 'start'
    else:
        raise RuntimeError("Konnte Betriebsystem nicht herraus finden")
    return startcmd
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du wirst es vielleicht nicht glauben, aber so sollte deine Lösung aussehen. Im Idealfall erstellst du noch deine eigene Exception, dann kannst du etwas granularer mit den Fehlern umgehen. RuntimeException ist noch etwas sehr allgemein.

Code: Alles auswählen

class UnsupportedOSError(Exception): pass

def sysprog():
    ...
    else:
        raise UnsupportedOSError("Konnte ...")
Edit: etwas kürzer wird es, wenn du gleich in den if/elif-Zweigen ein return machst, dann kannst du dir am Ende das else sparen:

Code: Alles auswählen

def sysprog():
    """
    BENUTZE DOC-STRINGS ZUR BESCHREIBUNG VON FUNKTIONEN
    Betriebssytem ermitteln und Datei mit Standardprogramm öffnen.
    """

    if sys.platform.startswith('lin'):
        return 'xdg-open'
    elif sys.platform.startswith('darwin'):
        return 'open'
    elif sys.platform.startswith('win'):
        return 'start'

    raise UnsupportedOSError("Konnte Betriebsystem nicht herraus finden")
Das Leben ist wie ein Tennisball.
Benutzeravatar
snafu
User
Beiträge: 6846
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Alternativvorschlag mit Wörterbuch und Nutzung von `platform.system()`:

Code: Alles auswählen

def get_starter():
    try:
        return {'Windows': 'start',
                'Linux': 'xdg-open',
                'Darwin': 'open'
               }[platform.system()]
    except KeyError:
        raise RuntimeError(
                'Passender Starter konnte nicht ermittelt werden')
Ist natürlich etwas fortgeschrittener und mag teils Geschmackssache sein. In Python tendiert man aber generell eher zu Wörterbüchern als zu einem Haufen von `if`/`elif`-Konstrukten. Wobei sich die Anhäufung hier natürlich noch in Grenzen hält.

Früher oder später würde ich anstatt `RuntimeError` wohl eine eigene Exception bevorzugen (sprach EyDu ja schon an). Der neue Exception-Typ kann aber IMHO durchaus von `RuntimeError` abgeleitet werden.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

snafu hat geschrieben: In Python tendiert man aber generell eher zu Wörterbüchern als zu einem Haufen von `if`/`elif`-Konstrukten. Wobei sich die Anhäufung hier natürlich noch in Grenzen hält.
+1 :-)

Ich war schon drauf und dran auf mein Textmenü-Tutorial (erneut) hinzuweisen, alleine aus der Erkenntnis, dass Nobuddy immer noch nicht den Blick für *zusammenhängende* oder *voneinander abhängige* Daten hat. Klar, muss man das bei drei Elemente nicht zwangsweise - zumal da eher kaum etwas hinzukommen wird - aber als Fingerübung schadet so etwas nie :-)

Denn Code wie dieser ist eben umständlich.

Code: Alles auswählen

    linux = sys.platform.startswith('lin')
     osx = sys.platform.startswith('os')
     windows = sys.platform.startswith('win')
     if linux:
         standardedit = 'xdg-open'
     elif osx:
         standardedit = 'open'
     elif windows:
         standardedit = 'start'
Wenn man dreimal dieselbe Funktion mit verschiedenen Parametern aufruft und abhängig vom Ergebnis dann ein anderes Datum bestimmt, dann sollten eben die Alarmglocken schrillen, dass man Copy&Paste-Programmierung betreibt...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Nobuddy
User
Beiträge: 1018
Registriert: Montag 30. Januar 2012, 16:38

Hallo EyDu und snafu,
beide Beispiele von Euch sind wirklich klasse und für mich auch verständlich.
Der Code von EyDu, ist so wie ich ihn bisher kenne.
snafuś Code hat aber was für sich und imponiert mir sehr.
snafu hat geschrieben:Früher oder später würde ich anstatt `RuntimeError` wohl eine eigene Exception bevorzugen (sprach EyDu ja schon an). Der neue Exception-Typ kann aber IMHO durchaus von `RuntimeError` abgeleitet werden.
Das wäre dann wohl 'UnsupportedOSError'. Da muß ich mich aber noch mehr damit auseinandersetzen.

@Hyperion, es ist nicht einfach Altlasten abzuschütteln ... und ich weiß selbst, daß in meinem Code noch etliches zu ändern ist.
Aber, wie sagt man so schön "Erkenntnis ist der erste Schritt" ... :wink:
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

ich würde es vielleicht so machen:

Code: Alles auswählen

import sys

CMD_INFO = {
    'win': 'start',
    'linux': 'xdg-open',
    'darwin': 'open' # Mac OS X
}

def get_cmd():
    for indetifier, cmd in CMD_INFO.items():
        if sys.platform.startswith(indetifier):
            return cmd
    raise UnsupportedOSError("Konnte Betriebsystem nicht herraus finden")

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Darf ich euch mal fragen was "herraus finden" ist? Ich kenne nur das Wort "herausfinden", aber wenn man in Bayern lebt hat man kein Gespür für die deutsche Sprache.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten