Python - tkinter text eingabe in variable?
Hallo,
ich habe folgendes programmiert:
import tkinter as tk
import os
root = tk.Tk()
root.geometry("400x240")
def encrypt(filename):
to_encrypt = open(filename, "rb").read()
size = len(to_encrypt)
key = os.urandom(size)
with open(filename + ".lqk", "wb") as key_out:
key_out.write(key)
encrypted = bytes(a ^ b for (a, b) in zip(to_encrypt, key))
with open(filename, "wb") as encrypted_out:
encrypted_out.write(encrypted)
filename = textExample.get(1.0, tk.END+"-1c")
encrypt(filename)
def decrypt(filename, key):
file = open(filename, "rb").read()
key = open(key, "rb").read()
decrypted = bytes(a ^ b for (a, b) in zip(file, key))
with open(filename, "wb") as decrypted_out:
decrypted_out.write(decrypted)
fileTest = filename + ".lqk"
try:
os.remove(fileTest)
except OSError as e:
print(e)
else:
print("Datei erfolgreich gelöscht!")
filename = textExample.get(1.0, tk.END+"-1c")
decrypt(filename, filename + ".lqk")
textExample=tk.Text(root, height=10)
textExample.pack()
btnEncrypt=tk.Button(root, height=1, width=10, text="Encrypt",
command=encrypt)
btnDecrypt=tk.Button(root, height=1, width=10, text="Decrypt",
command=decrypt)
btnEncrypt.pack()
btnDecrypt.pack()
root.mainloop()
Nur leider funktioniert dies nicht. In der Debugging Console bekomme ich folgende Fehlermeldung:
Bei der Encrypt Funktion:
PS C:\Users\elias\Desktop\Python> c:; cd 'c:\Users\elias\Desktop\Python'; & 'C:\Users\elias\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\launcher' '52518' '--' 'c:\Users\elias\Desktop\Python\main.py'
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
TypeError: encrypt() missing 1 required positional argument: 'filename'
Decrypt Funktion:
Traceback (most recent call last):
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
TypeError: decrypt() missing 2 required positional arguments: 'filename' and 'key'
Wie kann ich das Problem jetzt lösen?
Danke im Vorraus!
VG!
4 Antworten
Ändere deine beiden Funktionen:
def encrypt():
filename=textExample.get(1.0, tk.END+"-1c")
# ... usw.
bzw.:
def decrypt():
filename = textExample.get(1.0, tk.END+"-1c")
# ...
key = open(filename + ".lqk", "rb").read()
# ... usw.
und entferne jeweils die beiden letzten Zeilen:
filename= ....
# und
encrypt(...)
# bzw.
decrypt(...)
Dein neuer Code sieht dann so aus:
import tkinter as tk
import os
root = tk.Tk()
root.geometry("400x240")
def encrypt():
filename=textExample.get(1.0, tk.END+"-1c")
to_encrypt = open(filename, "rb").read()
size = len(to_encrypt)
key = os.urandom(size)
with open(filename + ".lqk", "wb") as key_out:
key_out.write(key)
encrypted = bytes(a ^ b for (a, b) in zip(to_encrypt, key))
with open(filename, "wb") as encrypted_out:
encrypted_out.write(encrypted)
def decrypt():
filename = textExample.get(1.0, tk.END+"-1c")
file = open(filename, "rb").read()
key = open(filename + ".lqk", "rb").read()
decrypted = bytes(a ^ b for (a, b) in zip(file, key))
with open(filename, "wb") as decrypted_out:
decrypted_out.write(decrypted)
fileTest = filename + ".lqk"
try:
os.remove(fileTest)
except OSError as e:
print(e)
else:
print("Datei erfolgreich gelöscht!")
textExample=tk.Text(root, height=10)
textExample.pack()
btnEncrypt=tk.Button(root, height=1, width=10, text="Encrypt", command=encrypt)
btnDecrypt=tk.Button(root, height=1, width=10, text="Decrypt", command=decrypt)
btnEncrypt.pack()
btnDecrypt.pack()
root.mainloop()
Gern geschehen.
Wenn du deinen alten mit dem neuen Code vergleichst kannst du nachvollziehen warum es jetzt funktioniert.
Ich bins nochmal :P
Habe mir nun was anders Überlegt. Direkt zum Start des Programms soll der Benutzer eine Datei auswählen. Dann soll der Pfad der Datei automatisch als filename gesetzt werden und man soll anschließend den Pad zur Datei und die Encrypt / Decrypt Buttons sehen. Den Pfad am besten unveränderbar (also wie so grau hinterlegt -> einfach nur "print"?)
Der Code (welcher leider nicht funktioniert):
from fileinput import filename
import tkinter as tk
import os
from tkinter.messagebox import *
from tkinter import filedialog
from tkinter.filedialog import askopenfile
root = tk.Tk()
root.title("F1le Pr8tect")
root.geometry("400x500")
def select_file():
filename = filedialog.askopenfilename()
select_file()
def encrypt():
to_encrypt = open(filename, "rb").read()
size = len(to_encrypt)
key = os.urandom(size)
with open(filename + ".lqk", "wb") as key_out:
key_out.write(key)
encrypted = bytes(a ^ b for (a, b) in zip(to_encrypt, key))
with open(filename, "wb") as encrypted_out:
encrypted_out.write(encrypted)
print(showinfo("Encryption Successfull", "Encryption Successfull"))
def decrypt():
file = open(filename, "rb").read()
key = open(filename + ".lqk", "rb").read()
decrypted = bytes(a ^ b for (a, b) in zip(file, key))
with open(filename, "wb") as decrypted_out:
decrypted_out.write(decrypted)
fileTest = filename + ".lqk"
try:
os.remove(fileTest)
except OSError as e:
print(e)
else:
print("Datei erfolgreich gelöscht!")
print(showinfo("Decryption Successfull", "Decryption Successfull"))
textExample=tk.Text(root, height=2)
textExample.pack()
btnEncrypt=tk.Button(root, height=1, width=10, text="Encrypt", command=encrypt)
btnDecrypt=tk.Button(root, height=1, width=10, text="Decrypt", command=decrypt)
btnEncrypt.pack()
btnDecrypt.pack()
root.mainloop()
er findet, wie immer, den filename wert nicht ^^
ok, das er den filename wert jetzt doch hat hab ich hinbekommen. aber wie bekomme ich den Wert jetzt unveränderbar oben in die Textzeile (welche am besten grau hinterlegt sein sollte)
# Folgende "from import" können weg:
#from fileinput import filename
#from tkinter import filedialog
#from tkinter.filedialog import askopenfile
# Dafür fügst du den hier ein:
from tkinter.filedialog import askopenfilename
#... Weiterer Code ...
def select_file():
filename = askopenfilename()
return filename
filename=select_file()
# ... restlicher Code ...
Anstatt tk.Text würde ich tk.Label benutzen:
# Das hier ersetzen
#textExample=tk.Text(root, height=2)
#textExample.pack()
# mit:
label=tk.Label(root, text=filename)
label.pack()
Alles klar. Dann noch zwei Fragen.
1.) Wie kann ich einen Button realisieren, welcher die Ziel Datei ändert? Also das ich das Programm nicht jedes Mal neu starten muss, um eine weitere Datei zu verschlüsseln...
Was mich auf den nächste Punkt bringt..
2. Ist es möglich auch mehrere Dateien gleichzeitig, oder ansonsten auch nacheinander zu verschlüsseln (Mehrfachauswahl), wenn ja, wie?
Ich danke dir für alles!!
Frage 1 hat sich ja geklärt über die select_file Funktion, welche du oben geschrieben hattest, oder?
Zu 1.
So könntest du eine Dateiauswahl machen:
# Die Funktion select_file änderst du entsprechend:
filename=""
def select_file():
global filename
filename = askopenfilename()
label.configure(text=filename)
#filename=select_file() <-- kann weg
#...
# Und fügst einen weiteren Button hinzu:
btnFile=tk.Button(root, height=1, width=10, text="Datei", command=select_file)
btnFile.pack()
#...
Zu 2.
Du speicherst die Dateipfade der ausgewählten Dateien in z.B. einer Liste und führst mit Hilfe einer for Schleife für jeden Eintrag die jeweilige Funktion (encrypt oder decrypt) aus.
Danke! Ich versuche mich daran. Bei Problemen melde ich mich :)
Die jeweils letzte Zeile in den Funktionen encrypt() bzw. decrypt()
a) Du entfernst für deine beiden Funktionen die Parameter und ermittelst ihre Werte stattdessen innerhalb der Funktion.
def encrypt():
filename = # ...
""" ... """
def decrypt():
filename = # ...
key = # ...
""" ... """
Du möchtest doch sicherlich eh die Eingaben aus Textfeldern holen.
b) Du setzt einen Lambda-Eindruck ein:
filename = # ...
btnEncrypt=tk.Button(root, height=1, width=10, text="Encrypt", command=lambda: encrypt(filename))
Der Lambda-Ausdruck kapselt im Grunde deinen Funktionsaufruf in einer eigenen Funktion, die aufgerufen wird, sobald der Nutzer auf den Button drückt.
Voraussetzung wäre bei diesem Weg allerdings, dass die Werte deiner ursprünglichen Parameter schon bei Programmstart bekannt sind.
der filename und damit auch der ort der .lqk (Key-)Datei sind ja erst nach Eingabe des Benutzers bekannt... also was muss ich jetzt statt def encrypt bzw. def decrypt schreiben?
command=decrypt
command=encrypt
du brauchst dort natürlich auch argumente.
Wenn ich
command=encrypt(filename)
und
command=decrypt(filename, filename + ".lqk")
schreibe, merkt er aber schon vorher, das die nicht definiert sind...
"filename" is not definedPylance (reportUndefinedVariable)
Jetzt kommt die Fehlermeldung:
PS C:\Users\elias\Desktop\Python> c:; cd 'c:\Users\elias\Desktop\Python'; & 'C:\Users\elias\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\launcher' '49938' '--' 'c:\Users\elias\Desktop\Python\main.py'
PS C:\Users\elias\Desktop\Python> c:; cd 'c:\Users\elias\Desktop\Python'; & 'C:\Users\elias\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\launcher' '50138' '--' 'c:\Users\elias\Desktop\Python\main.py'
PS C:\Users\elias\Desktop\Python> c:; cd 'c:\Users\elias\Desktop\Python'; & 'C:\Users\elias\AppData\Local\Programs\Python\Python310\python.exe' 'c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\launcher' '58735' '--' 'c:\Users\elias\Desktop\Python\main.py'
Traceback (most recent call last):
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
exec(code, run_globals)
File "c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
cli.main()
File "c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
run()
File "c:\Users\elias\.vscode\extensions\ms-python.python-2021.12.1559732655\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 268, in run_path
code, fname = _get_code_from_file(run_name, path_name)
File "C:\Users\elias\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 242, in _get_code_from_file
code = compile(f.read(), fname, 'exec')
File "c:\Users\elias\Desktop\Python\main.py", line 41
command=encrypt(filename)
^^^^^^^^^^^^^^^^^
SyntaxError: invalid syntax. Perhaps you forgot a comma?
Du hast es zwar schon gefixt aber mit den klammern kann es nicht gehen weil die Funktion dann direkt ausgeführt werden würde und dann kommt es zu fehlern...
Der Code kommt mir bekannt vor aus dem Video von Algo Verstehen... xD Also du scheinst den Funktionen in Tkinter keine Argumente übergeben aber die wollen welche haben....
Haha alles gut habe das Script von ihm auch weiter benutzt ist einfach genial der Typ...
und sollte ich die angaben unter filename / key jetzt ändern (wenn ja in was), oder löschen? Problem ist halt nach wie vor das bei den "command" aufrufen vom tkinter.button die paras nicht bekannt sind...