1xAlle Fehler

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.
Antworten
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

Hallo brauche Hilfe :roll: :roll: :roll:
lerne gerade Python zu programmieren und komme nicht weiter.

Versuche gerade einen Vokabeltrainer nach zu programmieren und verstehe den Fehler nicht da in dem Tutorial der gleiche Befehl "1xAlle" ist und funktioniert.

Kann mir da jemand weiterhelfen. Suche mir den Wolf aber versteh nicht woran es liegt.

Code: Alles auswählen

# Externe Module
import os, sqlite3, tkinter, random

# Falls keine Datenbankdatei vorhanden: Erstellen, mit Startdaten
if not os.path.exists("vokabel.db"):
    con = sqlite3.connect("vokabel.db")
    cursor = con.cursor()
    sql = "CREATE TABLE daten(id INTEGER PRIMARY KEY, deu TEXT, eng TEXT, fra TEXT)"
    cursor.execute(sql)
    startdaten = [["suchen", "to look for", "chercher"],
                  ["abkürzen", "to abbreviate", "raccourcir"],
                  ["nützlich", "useful", "utile"],
                  ["beraten", "to advise", "conseiller"],
                  ["einfach", "easy", "simple"],
                  ["ankündigen", "to announce", "annoncer"]]
    for gruppe in startdaten:
        sql = "INSERT INTO daten(deu, eng, fra) VALUES('" + gruppe[0] \
              + "', '" + gruppe[1] + "', '" + gruppe[2] + "')"
        print(sql)
        cursor.execute(sql)
        con.commit()
    con.close()

# Vokabel speichern
def vokabelSpeichern():
    if enDeu.get() == "" or enEng.get() == "" or enFra.get() == "":
        tkinter.messagebox.showwarning("Warnung", "Alle drei Eingabefelder füllen")
        return

    # Prüfen, ob Vokabel bereits vorhanden ist
    con = sqlite3.connect("vokabel.db")
    cursor = con.cursor()
    sql = "SELECT * FROM daten WHERE deu = '" + enDeu.get() + "'"
    cursor.execute(sql)
    ergebnis = cursor.fetchall()

    # Falls Vokabel bereits vorhanden ist, ggf. überschreiben
    if ergebnis:
        antwort = tkinter.messagebox.askyesno("Vokabel bereits vorhanden",
            "Wollen Sie Folgendes ersetzen?\n" + ergebnis[0][1] +
            "; " + ergebnis[0][2] + "; " + ergebnis[0][3])
        if antwort == 1:
            sql = "UPDATE daten SET eng = '" + enEng.get() + "', fra = '" + \
                  enFra.get() + "' WHERE deu = '" + enDeu.get() + "'"
            print(sql)
            cursor.execute(sql)
            con.commit()

    else:
        sql = "INSERT INTO daten (deu, eng, fra) VALUES('" + enDeu.get() \
              + "', '" + enEng.get() + "', '" + enFra.get() + "')"
        print(sql)
        cursor.execute(sql)
        con.commit()

    con.close()

# Vokabel löschen
def vokabelLoeschen():
    if enDeu.get() == "" or enEng.get() == "" or enFra.get() == "":
        tkinter.messagebox.showwarning("Warnung", "Alle drei Eingabefelder füllen")
        return

    # Löschen, falls alle drei Einträge übereinstimmen
    con = sqlite3.connect("vokabel.db")
    cursor = con.cursor()
    sql = "DELETE FROM daten WHERE deu = '" + enDeu.get() + "' AND eng = '" + \
          enEng.get() + "' AND fra = '" + enFra.get() + "'"
    print(sql)
    cursor.execute(sql)
    con.commit()
    con.close()

# Test starten, Frage stellen, Eingabe prüfen
testAktiv = False
def startenStellenPruefen():
    global testAktiv, listeEins, listeZwei, nummerAuswahl
    
    # Falls Test noch nicht gestartet wurde
    if not testAktiv:
        # Wurde eine Auswahl getroffen?
        if liKombi.curselection():
            kombi = int(liKombi.curselection()[0])
        else:
            tkinter.messagebox.showwarning("Warnung", "Treffen Sie zunächst eine Auswahl")
            return

        # Test starten
        buTestStarten["text"] = "Prüfen / Nächste Vokabel"
        testAktiv = True
        nummerAuswahl = -1

        # Datensätze laden
        con = sqlite3.connect("vokabel.db")
        cursor = con.cursor()
        sql = "SELECT * FROm daten"
        cursor.execute(sql)

        # Listen füllen
        listeEins = []
        listeZwei = []
        for dsatz in cursor:
            if kombi == 0:
                listeEins.append(dsatz[1])
                listeZwei.append(dsatz[2])
            elif kombi == 1:
                listeEins.append(dsatz[2])
                listeZwei.append(dsatz[1])
            elif kombi == 2:
                listeEins.append(dsatz[1])
                listeZwei.append(dsatz[3])
            elif kombi == 3:
                listeEins.append(dsatz[3])
                listeZwei.append(dsatz[1])
            elif kombi == 4:
                listeEins.append(dsatz[2])
                listeZwei.append(dsatz[3])
            else:
                listeEins.append(dsatz[3])
                listeZwei.append(dsatz[2])
        con.close()

    # Antwort prüfen, falls nicht allererste Frage
    if nummerAuswahl != -1:
        if enAntwort.get() == listeZwei[nummerAuswahl]:
            lbBew["text"] = "Richtig: " + listeEins[nummerAuswahl] + " = " + listeZwei[nummerAuswahl]
            del listeEins[nummerAuswahl]
            del listeZwei[nummerAuswahl]
        else:
            lbBew["text"] = "Falsch: " + listeEins[nummerAuswahl] + " = " + listeZwei[nummerAuswahl]

    # Test ist zu Ende?
    if not listeEins:
        tkinter.messagebox.showinfo("Info", "Alles gelöst, gratuliere")

        # Startzustand herstellen
        buTestStarten["text"] = "Test starten"
        lbFrage["text"] = "(Frage)"
        enAntwort.delete(0, "end")
        lbBew["text"] = "(Bewertung)"
        testAktiv = False
        nummerAuswahl = -1
        return

    # Nächste Frage stellen
    nummerAuswahl = random.randint(0, len(listeEins) - 1)
    lbFrage["text"] = listeEins[nummerAuswahl] + " ="
    enAntwort.delete(0, "end")

# Alle Vokabeln anzeigen
def alleAnzeigen():
    con = sqlite3.connect("vokabel.db")
    cursor = con.cursor()
    sql = "SELECT * FROM daten order by deu"
    cursor.execute(sql)
    lxAlle.delete(0, "end")
    for dsatz in cursor:
        lxAlle.insert("end", dsatz[1] + "; " + dsatz[2] + "; " + dsatz[3])
    con.close()

# Anzeige löschen
def anzeigeLoeschen():
    lxAlle.delete(0, "end")

# Auf Auswahl eines Eintrags reagieren
def lxAlleClick(e):
    nr = int(lxAlle.curselection()[0])
    inhalt = lxAlle.get(nr)
    teile = inhalt.split(";")
    enDeu.delete(0, "end")
    enEng.delete(0, "end")
    enFra.delete(0, "end")
    enDeu.insert("end", teile[0])
    enEng.insert("end", teile[1][1:])
    enFra.insert("end", teile[2][1:]) 

# Programm beenden
def ende():
    main.destroy()

# Hauptfenster
main = tkinter.Tk()
main["height"] = 480
main["width"] = 600

# Drei Label zum Ändern der Vokabeln
lbDeu = tkinter.Label(main, text="deutsch:")
lbDeu.place(x=10, y=10)
lbEng = tkinter.Label(main, text="englisch:")
lbEng.place(x=140, y=10)
lbFra = tkinter.Label(main, text="französisch:")
lbFra.place(x=270, y=10)

# Drei Entries zum Ändern der Vokabeln
enDeu = tkinter.Entry(main, width=13)
enDeu.place(x=10, y=40)
enEng = tkinter.Entry(main, width=13)
enEng.place(x=140, y=40)
enFra = tkinter.Entry(main, width=13)
enFra.place(x=270, y=40)

# Zwei Buttons zum Speichern bzw. Löschen einer Vokabel
buSpeichern = tkinter.Button(main, text="Speichern", command=vokabelSpeichern)
buSpeichern.place(x=410, y=30)
buLoeschen = tkinter.Button(main, text="Löschen", command=vokabelLoeschen)
buLoeschen.place(x=510, y=30)

# Label und Listbox zur Auswahl der Sprachkombination
lbKombi = tkinter.Label(main, text="Sprachkombination für Test:")
lbKombi.place(x=10, y=80)

liKombi = tkinter.Listbox(main, width=25, height=0)
liKombi.insert("end", "deutsch / englisch")
liKombi.insert("end", "englisch / deutsch")
liKombi.insert("end", "deutsch / französisch")
liKombi.insert("end", "französisch / deutsch")
liKombi.insert("end", "englisch / französisch")
liKombi.insert("end", "französisch / englisch")
liKombi.place(x=10, y=110)

# Button zum Starten des Tests
buTestStarten = tkinter.Button(main, text="Test starten", command=startenStellenPruefen)
buTestStarten.place(x=250, y=110)

# Zwei Label und ein Entry für den Test
lbFrage = tkinter.Label(main, text="(Frage)")
lbFrage.place(x=250, y=165)
enAntwort = tkinter.Entry(main, width=13)
enAntwort.place(x=410, y=165)
lbBew = tkinter.Label(main, text="(Bewertung)")
lbBew.place(x=250, y=210)

# Liste mit Scrollbalken, um alle Vokabeln anzuzeigen
lbListe = tkinter.Label(main, text="Alle Vokabeln:")
lbListe.place(x=10, y=260)
frListe = tkinter.Frame(main)
frListe.place(x=10, y=290)

scbAlle = tkinter.Scrollbar(frListe, orient="vertical")
lxAlle = tkinter.Listbox(frListe, width=40, height=7, yscrollcommand=scbAlle.set)
scbAlle["command"] = lxAlle.yview
lxAlle.pack(side="left")
scbAlle.pack(side="left", fill="y")
lxAlle.bind("<<ListboxSelect>>", lxAlleClick)

# Zwei Buttons zum Anzeigen aller Vokabeln und zum Löschen der Anzeige
buAlleAnzeigen = tkinter.Button(main, text="Alle Vokabeln anzeigen", command=alleAnzeigen)
buAlleAnzeigen.place(x=380, y=290)
buAnzeigeLoeschen = tkinter.Button(main, text="Anzeige löschen", command=anzeigeLoeschen)
buAnzeigeLoeschen.place(x=380, y=340)

# Ende
buEnde = tkinter.Button(main, text="Ende", command=ende)
buEnde.place(x=530, y=400)

# Hauptprogrammschleife starten
main.mainloop()


             
eckhard
User
Beiträge: 33
Registriert: Montag 14. Dezember 2015, 10:06
Wohnort: Karlsruhe

@paradiesvogel24. Welchen Fehler bekommst Du?

Wie hast Du das Skript gestartet? Ich habe (in Linux) das Skript in die Datei datei,pl kopiert, #!/usr/bin/python3 an den Anfang gesetzt,
chmod u+x datei.pl gemacht und dann mit ./datei.pl aufgerufen. Es wird ein Fenster ausgegeben. Buttons funktionieren.

Eckhard
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Zeile 167 nr = int(lxAlle.curselection()[0])

lxAlle.cuselection liefert manchmal ein leeres Tupel zurück.
Darauf muss du reagieren, sonst IndexError: tuple index out of range

Der Rest scheint zu funktionieren.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@paradiesvogel24: bei Deinem Programm mußt Du noch einiges aufräumen. Auf oberster Ebene sollten nur Definitionen und KONSTANTEN stehen, Du mischst ausführbaren Code und Funktionsdefinitionen wild durcheinander. In Zeile 17 stückelst Du SQL-Kommandos per + zusammen. Das solltest Du nie! machen. Das ist nicht nur unleserlich und fehleranfällig, dadurch können undurchsichtige Fehler entstehen, versuch mal o'clock als Vokabel einzufügen. `execute` kennt ein zweites Argument als Parameter:

Code: Alles auswählen

    for gruppe in startdaten:
        sql = "INSERT INTO daten(deu, eng, fra) VALUES(?, ?, ?)"
        cursor.execute(sql, gruppe)
Gleicher Fehler in Zeile 33, 43, 50, 67, etc.

Funktionen sollten alles was sie brauchen per Parameter erhalten. Globale Variablen machen ein Programm untestbar und Fehler sind schwer zu lokalisieren. Für GUI-Programme braucht man eigentlich zwangsläufig Objektorientierung.

Du solltest auch die Datenbankabfrage stärker von der Anzeigelogik trennen, also Funktionen schreiben, die nichts anderes machen, als die verschiedenen Datenbankabfragen. Dass an vielen Stellen jeweils eine eigene Datenbankverbindung aufgebaut ist, ist auch nicht gut.

Die Variablenschreibweise hält sich nicht an die übliche Konvention: klein_mit_unterstrich. Viele Namen sind zu generisch, listeEins und listeZwei sagen nicht, was denn nun in den Listen steht. die Präfixe lb, bu, lx sind nichtssagend. Ob etwas ein Knopf ist, oder nicht, braucht nicht im Variablennamen stehen, weil es durch seine Funktion sowieso klar wird.

Elemente sollte man nicht mit `place` positionieren, sondern entweder mit `grid` oder mit `pack`. Bei `place` funktioniert deine GUI nur unter Deinem Betriebssystem mit Deiner Auflösung. Bei anderen könnte das Programm unbenutzbar sein, weil Textfelder übereinander liegen oder aus dem Fenster herausgerutscht sind.
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

@ eckhard
Ich habe das Programm ganz normal mit Python mit der F5 taste dem Befehl:"Progtamm starten gestartet.

Leider kommt bei mir der Fehler: "invalid Syntax " und so komme ich erst gar nicht bis zum Button
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

@Sirius3
ich verstehe nur Bahnhof.

Seltsam das da so viele Fehler sein sollen wo ich doch das Programm eigentlich von dem Videokurs von Videobrain2 nachrprogrammiert habe
Die Jungs sollten doch wissen wie das richtig geht oder?

Seltsam ist nur wenn ich in den gleichen Zeilen den Code einsetze (in dem Fall von 240-243)

Code: Alles auswählen

scbAlle = tkinter.Scrollbar(frListe, orient="vertical")
lxAlle = tkinter.Listbox(frListe, width=40, height=7, yscrollcommand=scbAlle.set)
scbAlle["command"] = lxAlle.yview
lxAlle.pack(side="left")
...funktioniert es und das Programm startet obwohl es derselbe Text ist, kann doch nicht sein oder?

Kann ich in Python irgendwo die Zeilennummern einblenden?
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

@heiner88
wo siehst Du denn das ein leeres Feld zurück geliefert wurde?
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

paradiesvogel24 hat geschrieben:Seltsam das da so viele Fehler sein sollen wo ich doch das Programm eigentlich von dem Videokurs von Videobrain2 nachrprogrammiert habe
Die Jungs sollten doch wissen wie das richtig geht oder?
Das Programm ist vom Entwurf her wirklich schlecht und ein Beispiel, wie es nicht gemacht werden sollte. Das ist generell ein Problem bei solchen Online-Kursen, die sich an Teilnehmer wenden, die Python bzw. Programmieren lernen möchten und daher die Qualität des vorgesetzten noch gar nicht beurteilen können.
nezzcarth
User
Beiträge: 1634
Registriert: Samstag 16. April 2011, 12:47

paradiesvogel24 hat geschrieben: Seltsam das da so viele Fehler sein sollen wo ich doch das Programm eigentlich von dem Videokurs von Videobrain2 nachrprogrammiert habe
Die Jungs sollten doch wissen wie das richtig geht oder?
Ich kenne das Video nicht, aber wenn der Stil, den du gezeigt hast, so auch in dem Video vermittelt wird, spricht das nicht für das Video. Python zeichnet sich dadurch aus, dass es in der Community recht viele Konventionen/Best Practices gibt, die z.B. nahelegen, wie Code formatiert und strukturiert sein sollte, wie man Dinge benennt, wie man bestimmte, wiederkehrende Probleme idiomatisch löst und was man nicht tun sollte.

Hier im Forum tauchen immer wieder Schnipsel aus Lehrwerken oder Kursen auf, die nicht nach "echtem" Python aussehen. Die Lehrperson hat in diesen Fällen zwar scheinbar generelle Programmiererfahrung, aber sich vielleicht nicht besonders tiefgreifend mit den Besonderheiten von Python beschäftigt, sondern auf die Syntax geschaut und dann einfach so losgelegt, wie sie/er es von anderen Sprachen gewohnt ist. Andere Dinge sind auch in anderen Sprachen schlechte Angewohnheiten, auf deren Vermeidung bei Python besonders viel Wert gelegt wird, um sauberen, gut lesbaren Code zu erhalten. Ich weiß wie gesagt nicht, ob das bei dem Video auch so ist. Aber es wäre nicht ungewöhnlich. Insofern würde ich nicht unbedingt darauf setzen, dass das Video in allen Punkten richtig liegt und die Vorschläge von Sirius3 annehmen/umsetzen.

EDIT: kbr war schneller; aber wo ich das schon mal getippt hatte... :)
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

>>>wo siehst Du denn das ein leeres Feld zurück geliefert wurde?

Ich starte dein Programm mit IDLE.
Nach einer Weile bekommt man diesen Fehler angezeigt im IDLE-Fenster:
Exception in Tkinter callback
Traceback (most recent call last):
...
File "test.py", line 168, in lxAlleClick
nr = int(lxAlle.curselection()[0])
IndexError: tuple index out of range
Wegen [0] gibt es einen "Index out of range"-Fehler,
weil curselection() ein leeres Tupel zurückgibt.
heiner88
User
Beiträge: 65
Registriert: Donnerstag 20. Oktober 2016, 07:29

Falls du das Programm überhaupt nicht zum Laufen bekommst,
kannst du mal den Code in deinem ersten Beitrag in einen File zurückkopieren.
Und dann mit diesem File IDLE starten. Vielleicht hast du tabs-Probleme.
Bedenke auch, dass dein Programm Python 3.x braucht (nicht Python 2.7).
Ich habe Windows 7 mit Python 3.6.2 benützt.
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

@kbr
Das ist generell ein Problem bei solchen Online-Kursen, die sich an Teilnehmer wenden, die Python bzw. Programmieren lernen möchten und daher die Qualität des vorgesetzten noch gar nicht beurteilen können.
Na das hört sich ja nicht so toll an.
Hatte gedacht das Video2brain weiss was sie da tun und wissen welche Dozenten sie mit welchem Wissen dort einsetzen.

Wollte mir das lernen durch die Videos etwas vereinfachen. Mal gut das ich mir den Kurs geliehen und nicht verkauft hatte.

Wie kann ich denn wissen welche Lehrwerke das Programmieren mit Python gut sind.
paradiesvogel24
User
Beiträge: 36
Registriert: Dienstag 31. Oktober 2017, 18:06

@nezzcarth
nezzcarth hat geschrieben:
paradiesvogel24 hat geschrieben: Andere Dinge sind auch in anderen Sprachen schlechte Angewohnheiten, auf deren Vermeidung bei Python besonders viel Wert gelegt wird, um sauberen, gut lesbaren Code zu erhalten. Ich weiß wie gesagt nicht, ob das bei dem Video auch so ist. Aber es wäre nicht ungewöhnlich.
Ja das ist natürlich alles Käse.
Wie schon geschrieben der Code ist genau so im Video wie eingefügt.

Wenn da soviel Schrott auf dem Markt ist und jeder alles anbieten kann macht es für die Programmieranfänger nicht unbedingt einfacher das Programmieren zu erlernen.

Wo finde ich denn die wertvollen Tipps wie ich am besten den Code: formatieren, strukturieren und analysieren sollte. habe das nicht gefunden.

Arbeite gerade das Buch: "Programmieren von Kopf bis Fuss an" und hoffe das es besser ist obwohl es dort erst einmal ums Gehirn gerechte lernen geht und nicht um die Sortierung des Codes. Das soll wohl in einem anderem Buch erklärt werden. Da empfiehlt der Autor: dieses https://www.amazon.de/Einf%C3%BChrung-P ... +in+python

Kennt jemand die Bücher"Von Kopf bis Fuss?
Hat jemand damit gute Erfahrungen gemacht?
Habe den Tipp vom Freund bekommen der programmiert.
Habe bei Amazon darüber viele Lobeshymnen gesehen.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@paradiesvogel24: Die Kopf bis Fuß Reihe verfolgt einen didaktischen Ansatz, der insbesondere für Leser, die bei einem neuen Thema den Wald vor lauter Bäumen nicht mehr sehen und von allem erschlagen sind, hilfreich sein kann. Das ist schonmal positiv; als Nachschlagewerke sind sie ungeeignet. Ob der Inhalt dagegen gut ist, hängt wieder von den einzelnen Autoren ab. Da mag die Qualität variieren.

Das Buch von Mark Lutz ist zu empfehlen, aber auch ziemlich weitschweifig. Je nach Vorwissen muß das kein Nachteil sein. Trotz komischen Cover ist auch das folgende Buch gut für Einsteiger: Python Crashkurs.
Antworten