@blackjack; danke für die Erläuterung, das sehe ich auch so. Leider funktioniert das ohne Anführungszeichen (als Variable) auch nicht, hatte ich deets schon geschrieben.
data = selection[12] ## string aus der Datenbank
f = io.BytesIO(data)
photo=image.open(f)
Wo ist denn da der Fehler ? Wie funktioniert es?
BLOB String aus SQLite DB wieder als Image anzeigen
- __blackjack__
- User
- Beiträge: 14002
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Was heisst denn ”funktioniert nicht” und was ist `image`?
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Moin, danke, dass ihr dran bleibt
. Ich habe das DB Lesestatement mal direkt vor die Ausgabe geschoben und bekomme jetzt eine andere Meldung:
lfdnr="LfdNR"
connection = sqlite3.connect(datenbank)
cursor = connection.cursor()
cursor.execute(f"SELECT LfdNr, Datei_klein FROM Inventardaten Where {'lfdnr'} = {selection[0]}")
result = cursor.fetchall()
for r in result:
print (r[0], r[1]) # nur für Test
data = r[1]
connection.close()
# Konvertieren
f = io.BytesIO(data)
photo=Image.open(f)
# Foto in TopFrame ausgeben
foto_label=tk.Label(topFrame,anchor='e', image=photo)
foto_label.image=photo
foto_label.config(image=photo)
foto_label.grid(row=1, column=12, columnspan=3, rowspan=3, padx='5', pady='5', sticky='es')
Hier die DDL zur DB:
CREATE TABLE Inventardaten (
LfdNR INTEGER PRIMARY KEY AUTOINCREMENT,
DB_Status CHAR,
Datei_klein BLOB,
Datei_original VARCHAR
);

lfdnr="LfdNR"
connection = sqlite3.connect(datenbank)
cursor = connection.cursor()
cursor.execute(f"SELECT LfdNr, Datei_klein FROM Inventardaten Where {'lfdnr'} = {selection[0]}")
result = cursor.fetchall()
for r in result:
print (r[0], r[1]) # nur für Test
data = r[1]
connection.close()
# Konvertieren
f = io.BytesIO(data)
photo=Image.open(f)
# Foto in TopFrame ausgeben
foto_label=tk.Label(topFrame,anchor='e', image=photo)
foto_label.image=photo
foto_label.config(image=photo)
foto_label.grid(row=1, column=12, columnspan=3, rowspan=3, padx='5', pady='5', sticky='es')
Hier die DDL zur DB:
CREATE TABLE Inventardaten (
LfdNR INTEGER PRIMARY KEY AUTOINCREMENT,
DB_Status CHAR,
Datei_klein BLOB,
Datei_original VARCHAR
);
Wäre hilfreich, wenn du die andere Meldung auch verraten würdest. Was man niemals machen darf, ist Parameter in SQL-Statenents hineinzuformatieren. LfdNr steckst du rein, warum fragst du sie auch wieder ab? Wie bist du auf die Idee gekommen, einen literalen String als Formatangabe zu verwenden? Die for-Schleife ist komisch, da du alles wegwirfst, bis auf den letzten Eintrag.
oh, vergessen. Hier die Meldung "_tkinter.TclError: image "<PIL.JpegImagePlugin.JpegImageFile image mode=L size=250x200 at 0x523D530>" doesn't exist"
Ok, das Lesestatement ist nicht so gelungen, habe ich auch nur von anderer Stelle hier herein gebracht. LfdNr als Parameter und Ergebnis, einfach nur Ungläubigkeit bzw. für die Testausgabe.
Ok, das Lesestatement ist nicht so gelungen, habe ich auch nur von anderer Stelle hier herein gebracht. LfdNr als Parameter und Ergebnis, einfach nur Ungläubigkeit bzw. für die Testausgabe.
- __blackjack__
- User
- Beiträge: 14002
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
(Einiges wurde zwischenzeitlich schon besprochen, bin zu faul den Beitrag jetzt noch mal zu überarbeiten, sorry.)
@bigbonzo: Was hast Du Dir denn bei f"… {'lfdnr'} …" gedacht? Das sieht doch schon wieder danach aus als wenn Du Namen und literale Zeichenketten durcheinander bringst, denn das ist das gleiche wie f"… lfdnr …". Funktioniert natürlich hier trotzdem wenn der *Name* `lfdnr` an "LfdNR" gebunden ist weil SQL nicht zwischen Gross- und Kleinschreibung unterscheidet.
Spaltennamen in SQL zu formatieren ist zumindest komisch – Werte in SQL zu formatieren ist *falsch*. Das ist potentiell gefährlich und kann bei Datenbanken/Datenbankanbindungen die SQL-Anweisungen cachen, dazu führen das der Cache nicht genutzt werden kann wenn die SQL-Anweisung immer anders aussieht. Für Werte gibt es Platzhalter und das zweite Argument von `execute()`.
Da über den Primärschlüssel selektiert wird kann da nur (maximal) ein Ergebnis bei heraus kommen, da macht eine Schleife über ”alle” Ergebnisse wenig Sinn.
`f` ist wie die meisten einbuchstabigen Namen kein sinnvoller, guter Name. Wenn man `file` meint, sollte man das auch schreiben. Wenn man `image_file` schreibt, weiss der Leser sogar dass die Datei ein Bild enthält. Andererseits muss man auch nicht jedes Zwischenergebnis an einen Namen binden.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also `top_frame` statt `topFrame`.
Die `image`-Option vom Label wird unnötigerweise zweimal gesetzt.
Zwischenstand:
Hier dürfte jetzt das Problem sein das `Image` wahrscheinlich `PIL.Image` ist und das was `open()` da liefert nicht direkt als Bildobjekt für `tkinter` verwendet werden kann. Das hattest Du in einem der vorherigen Beiträge schon mal richtig gemacht mit `ImageTk` aus dem `PIL`-Package.
Ich verwende bei Datenbanken ja fast immer SQLAlchemy als Zwischenschicht. Selbst wenn man das ORM nicht verwendet, lässt sich so auch SQL dynamisch zusammenbauen ohne das man da mit SQL oder fehleranfälligen Zeichenketten hantieren muss. Und man ist unabhängiger von der am Ende verwendeten Datenbank.
@bigbonzo: Was hast Du Dir denn bei f"… {'lfdnr'} …" gedacht? Das sieht doch schon wieder danach aus als wenn Du Namen und literale Zeichenketten durcheinander bringst, denn das ist das gleiche wie f"… lfdnr …". Funktioniert natürlich hier trotzdem wenn der *Name* `lfdnr` an "LfdNR" gebunden ist weil SQL nicht zwischen Gross- und Kleinschreibung unterscheidet.
Spaltennamen in SQL zu formatieren ist zumindest komisch – Werte in SQL zu formatieren ist *falsch*. Das ist potentiell gefährlich und kann bei Datenbanken/Datenbankanbindungen die SQL-Anweisungen cachen, dazu führen das der Cache nicht genutzt werden kann wenn die SQL-Anweisung immer anders aussieht. Für Werte gibt es Platzhalter und das zweite Argument von `execute()`.
Da über den Primärschlüssel selektiert wird kann da nur (maximal) ein Ergebnis bei heraus kommen, da macht eine Schleife über ”alle” Ergebnisse wenig Sinn.
`f` ist wie die meisten einbuchstabigen Namen kein sinnvoller, guter Name. Wenn man `file` meint, sollte man das auch schreiben. Wenn man `image_file` schreibt, weiss der Leser sogar dass die Datei ein Bild enthält. Andererseits muss man auch nicht jedes Zwischenergebnis an einen Namen binden.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also `top_frame` statt `topFrame`.
Die `image`-Option vom Label wird unnötigerweise zweimal gesetzt.
Zwischenstand:
Code: Alles auswählen
...
with sqlite3.connect(datenbank) as connection:
cursor = connection.cursor()
cursor.execute(
"SELECT LfdNr, Datei_klein FROM Inventardaten WHERE lfdnr = ?",
[selection[0]],
)
result = cursor.fetchone()
if result:
_, image_data = result
photo = Image.open(io.BytesIO(image_data))
foto_label = tk.Label(top_frame, anchor=tk.E, image=photo)
foto_label.image = photo
foto_label.grid(
row=1,
column=12,
columnspan=3,
rowspan=3,
padx=5,
pady=5,
sticky=tk.SE,
)
Ich verwende bei Datenbanken ja fast immer SQLAlchemy als Zwischenschicht. Selbst wenn man das ORM nicht verwendet, lässt sich so auch SQL dynamisch zusammenbauen ohne das man da mit SQL oder fehleranfälligen Zeichenketten hantieren muss. Und man ist unabhängiger von der am Ende verwendeten Datenbank.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Hallo Leute, et löpp.
Habe mir die neue Fehlermeldung nochmal angesehen und im Netz gesucht. Dort den Hinweis "photo = ImageTk.PhotoImage(photo)" gefunden, läuft jetzt tadellos.
Habe gerade gelesen, dass du das auch so siehst, passt.
Euch vielen Dank für eure Hinweise und Geduld
Habe mir die neue Fehlermeldung nochmal angesehen und im Netz gesucht. Dort den Hinweis "photo = ImageTk.PhotoImage(photo)" gefunden, läuft jetzt tadellos.
Habe gerade gelesen, dass du das auch so siehst, passt.
Euch vielen Dank für eure Hinweise und Geduld
