Seite 1 von 1

Fehler code: Local Variable

Verfasst: Samstag 5. August 2017, 22:08
von GuardDog
Hallo ihr Python-Freaks :D,

ich habe ein Problem mit Variablen. Ich habe ein Programm, welches zwei Texte aus einem Entry-Widget in eine Datei schreiben soll. Um dies zu realisieren habe ich folgendes ausgearbeitet:

Code: Alles auswählen

from tkinter import *
import os
def hitenter(self):
    enterhit = 1
def setint():
    entry.delete(0, END)
    entry.insert(END, "Name der Variable:")
    while True:
        if (enter == 1):
            setint_name = entry.get()
            enter = 0
            break
    entry.delete(0, END)
    entry.insert(END, "Wert der Variable:")
    while True:
        if (enter == 1):
            setint_val = entry.get()
            enter = 0
            break
    with open('code.txt', 'a') as outfile:
        print(setint_name, "=", setint_val, ";", file=outfile)
root = Tk()
root.title("TexttoArduino")
root.resizable(width=False, height=False)
os.system("clear")
entry = Entry(root, width=61)
entry.bind("<Return>", hitenter)
global enter
enter = 0
btn_setint = Button(root, text="Variable verändern", width=17, command=setint)
btn_setint.grid(row=2, column=2, pady=2, padx=2)
entry.focus_set()
root.mainloop()
Leider bekomme ich den Fehler:

Code: Alles auswählen

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1699, in __call__
    return self.func(*args)
  File "/Users/Tim/Developing/PythonProjects/TexttoArduino/write.py", line 23, in setint
    if (enter == 1):
UnboundLocalError: local variable 'enter' referenced before assignment
Ich habe gelesen, dass ich "enter" als globale Variable definieren(?) soll, dies habe ich getan, hat aber nicht geklappt. :cry: :cry: :cry:

Re: Fehler code: Local Variable

Verfasst: Samstag 5. August 2017, 22:51
von BlackJack
@GuardDog: `enter` ist lokal in `setint()` und Du versuchst darauf lesend zuzugreifen *bevor* ein Wert zugewiesen wurde. Das `enter` hat nichts mit dem `enter` auf Modulebene zu tun. ``global`` hat auf Modulebene keinen Effekt. Und Du solltest es sowieso gleich wieder vergessen, denn ``global`` schafft mehr Probleme als es löst. Bei GUIs brauchst Du sowieso objektorientierte Programmierung (OOP) und mehr der brauchst Du kein ``global``. Und auch keine Variablen auf Modulebene.

Zudem funktioniert GUI, also ereignisbasierte Programmierung, nicht so wie Du Dir das vorstellst. Solange `setint()` läuft ist die GUI ”tot”. Änderungen die daran gemacht werden, oder Reaktionen auf den Benutzer funktionieren erst wieder wenn diese Rückruffunktion *beendet* ist, Du beendest die aber nicht solange der Benutzer nicht was eingegeben hat, das kann er aber aber erst wenn die Funktion beendet ist, die wartet aber das der Benutzer etwas eingibt, das kann er aber erst wenn die Funktion beendet ist, die wartet aber…

Re: Fehler code: Local Variable

Verfasst: Sonntag 6. August 2017, 10:39
von GuardDog
@BlackJack wie soll ich es dann realisieren? Würde es mit einem OK-Button funktionieren? Ich möchte ja, dass der Nutzer seine Eingabe bestätigt.

Re: Fehler code: Local Variable

Verfasst: Sonntag 6. August 2017, 11:11
von BlackJack
@GuardDog: Ob der Benutzer das mit der Eingabetaste oder einer Schaltfläche macht, oder ob beides möglich ist/sein soll, ändert nichts daran, dass das so wie Du das versuchst, grundsätzlich nicht funktioniert.

Wie gesagt, man braucht für eine GUI objektorientierte Programmierung. Also Zustand und Funktionen die darauf operieren in Klassen zusammen gefasst. Dazu muss man Funktionen schreiben. Also ”echte” Funktionen, die ausser Konstanten nichts verwenden was nicht als Argument übergeben wurde. Wenn man auf Modulebene gar nicht erst etwas anderes als Konstanten, Funktionen, und Klassen hat, kommt man auch nicht in Versuchung so etwas zu machen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Du versuchst hier vier Themen die aufeinander aufbauen (❶ linearer Programmfluss → ❷ Funktionen → ❸ Klassen → ❹ ereignisbasierter Programmfluss) auf einmal zu lernen, die Quelltexte sehen aber so aus als wärst Du noch nicht mit dem zweiten Thema „Funktionen“ wirklich durch.

Re: Fehler code: Local Variable

Verfasst: Sonntag 6. August 2017, 11:22
von Sirius3
@GuardDog: so funktionieren GUIs normalerweise nicht, wie Du Dir das vorstellst. Man hat für jede Größe ein eigenes Eingabefeld und einen Ok-Button. Zudem funktioniert die serielle Programmierung, wie Du sie gezeigt hast, mit GUIs nicht. Du mußt das Programmieren von GUIs erstmal lernen und davor noch Objektorientierte Programmierung, weil ohne kommst Du nicht weit.

Ich verstehe, dass Du möglichst schnell Erfolg mit Deinem Arduino-Programmierer haben willst, aber ohne Grundlagen verrennst Du Dich irgendwo.

Code: Alles auswählen

import tkinter as tk

class Application(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("TexttoArduino")
        self.variable_name = tk.StringVar()
        self.variable_value = tk.StringVar()
        tk.Label(self, text="Name der Variable:").grid(row=1,column=1)
        tk.Entry(self, text=self.variable_name, width=61).grid(row=1, column=2)
        tk.Label(self, text="Wert der Variable:").grid(row=2,column=1)
        tk.Entry(self, text=self.variable_value, width=61).grid(row=2, column=2)
        tk.Button(self, text="Variable verändern", width=17, command=self.setint).grid(row=3, column=2, pady=2, padx=2)
        
    def setint(self):
        with open('code.txt', 'a') as outfile:
            outfile.write("{}={};\n".format(
                self.variable_name.get(),
                self.variable_value.get(),
            ))
            
def main():
    root = Application()
    root.mainloop()

if __name__ == '__main__':
    main()