@Mahera: Importe gehören an den Anfang des Moduls, nicht in Funktionen versteckt.
Auf Modulebene gehört nur Code der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Da ist es dann verwirrend wenn man das `Tk`-Objekt auch `main` nennt.
Einbuchstabige Namen und kryptische Abkürzungen sollte man vermeiden. `o`, `b`, und `h` gehen gar nicht. Ein Name soll dem Leser vermitteln was der Wert dahinter bedeutet. `i` für eine ganze Zahl die als Index verwendet wird ist okay, weil man das aus der Mathematik kennt.
`df_help` ist zwar nicht zu kurz, aber zu nichtssagend.
Im ``if``-Zweig macht die Zuweisung an `h` keinen Sinn, da der Wert nirgends verwendet wird.
Im ``else``-Zeig wird aus der "FId"-Spalte eine Liste gemacht von der dann aber nur das erste Element im weiteren Verlauf verwendet wird. Da kann man ohne Liste auch einfach das erste Element verwenden.
Es wurde im letzten Thema ja bereits gesagt: Man formatiert keine Werte in SQL als Zeichenketten. Niemals nicht! Das ist gefährlich und potentiell auch ineffizient.
Der Kommentar bei der Definition von `b` ist komisch denn an der Stelle im Programmablauf hat der Benutzer ja noch gar keine Gelegenheit gehabt irgendwelche Checkbuttons an- oder abzuwählen.
`dfplott` wird nirgends verwendet, womit `b` nicht wirklich verwendet wird, womit `h` auch nicht wirklich verwendet wird.
Dann wird `data` mit der gleichen SQL-Abfrage erstellt wie auch schon `df_help` erstellt wurde. Vorausgesetzt zwischen den beiden Abfragen hat sich in der Datenbank nichts geändert, enthalten die also die gleichen Daten. Warum dann zwei Abfragen?
Die Initialisierung von `i` vor der Schleife ist genau so überflüssig wie das ``i = i+1`` am Ende der Schleife weil beide Werte nie irgendwo verwendet werden.
``for i in range(len(sequence)):`` ist in Python ein „anti pattern“. `DataFrame`-Objekte sind zwar in dem Sinne kein Sequenz-Objekt weil `len()` sich auf etwas anderes bezieht als das was über Indexzugriff und Iteration über das Objekt erreichbar ist, aber auch hier ist diese Konstruktion der falsche weg. Es gibt die `iterrows()`-Methode dafür.
Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln ist eher BASIC als Python. Du kennst doch bereits die `format()`-Methode. Und ab Python 3.6 gibt es f-Zeichenkettenliterale.
`Variable`-Objekten braucht man kein Master-Widget mitgeben, man kann ihnen aber gleich beim Erstellen einen Wert mitgeben und braucht den nicht danach setzen.
Und diese Objekte sind auch das was Du aufheben musst, denn da kann man ja abfragen was der Zustand ist. Im Gegensatz zu den `Checkbutton`-Objekten.
Für Kombinationen von den ”Himmelsrichtungen” hat `tkinter` auch Konstanten, man muss die also nicht einzeln mit ``+`` angeben sondern kann auch einfach beispielsweise `tk.NW` verwenden.
Eine SQL-Abfrage `question` zu nennen ist ungewöhnlich. Defaultwerte sollte man auch nur angeben wenn die tatsächlich allgemein Sinn machen.
Das Formatieren der Zugangsdaten in die ODBC-Verbindungs-Zeichenkette macht IMHO keinen grossen Sinn. Es ist ja gerade praktisch das man alle Daten in *einer* Zeichenkette haben kann, die man beispielsweise auch aus einer Konfigurationsdatei lesen könnte. Oder zumindest als Konstante definieren, damit man nicht im ganzen Programm nach Zugangsdaten suchen muss.
Was zum Henker bedeutet `df_DUT`? `pyodbc.Connection`-Objekte sind Kontextmanager, da braucht man dann also gar keinen Namen für dieses Zwischenergebnis. Und die `query`-Funktion wird auch sehr kurz.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import tkinter as tk
import pandas as pd
import pyodbc
ODBC_CONNECTION_STRING = (
"DRIVER={SQL Server};"
"SERVER=https;"
"database=name;"
"trusted_connection=yes;"
"UID=user;"
"PWD=password"
)
def query(sql):
with pyodbc.connect(ODBC_CONNECTION_STRING) as connection:
return pd.read_sql_query(sql, connection)
def main():
root = tk.Tk()
products = query(
"SELECT FId, ProId, Test from Tabelle2 where ProId='2903'"
)
if len(products) <= 1:
print("leer")
else:
calibriation_variables = []
for i, row in products.iterrows():
variable = tk.BooleanVar(value=True)
calibriation_variables.append(variable)
calibration = tk.Checkbutton(
root, text=f"{row[0]} {row[1:]}", variable=variable
)
calibration.select()
calibration.grid(row=i, column=1, sticky=tk.NW)
root.mainloop()
print("Ende gut, Alles gut")
if __name__ == "__main__":
main()