Seite 1 von 1
Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 02:49
von Miscelo
Hallo liebe Forumer. Hast Du einen Tipp, wie ich den Schleifendurchlauf unterbrechen kann, nachdem das Passwort gefunden wurde? Das Programm öffnet einen Zippfile von dem man das Pssswort vergessen hat. Ich habe mich in den Script auf 3-stellige Passwörter beschränkt. In "try" akzeptiert er kein 'break', da es keine Schleife ist. Oder ich schreibe das ganze Script noch mal um.
Code: Alles auswählen
import zipfile
import string
import itertools
myzip = zipfile.ZipFile("/Pfad/my.zip", mode='r')
#Funktion die Versucht mit einem Passwort den Zipfile zu entpacken.
def openzip(myzip,password):
try:
myzip.extractall("/Pfad/", pwd=str.encode(password))
print("Das Passwort vom Zipfile ist:" + password)
except:
pass
# Es wird ein String erzeugt der alle Buchstaben, klein und groß, Zahlen und Sonderzeichen enthält.
myletters = string.ascii_letters + string.digits + string.punctuation
# Funktion versucht alle möglichen Kombinationen von 'myletters' bis max. 3 Zeichen, da das Passwort nur drei Zeichen hat.
def tryPasswords():
for i in range(1,4):
for j in map("".join,itertools.product(myletters, repeat=i)): #map funktion bildet mit itertools kombinationen aus den Zeichen in der Variable myletters.
openzip(myzip,j)
print(j) # kann weggelassen werden
tryPasswords()
print("Finish")
myzip.close()
Danke auf jeden Fall erste einmal für die Hilfe im voraus.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 08:25
von sparrow
Auf Modulebene gehören nur die Definitionen von Konstanten, Funktionen und Klassen. Alles andere verschwindet in eine Funktion main() und die ruft man über den in Python üblichen Passus am Ende des Scripts auf:
Gewöhn es dir lieber gleich an, dann hast du später weniger Schweierigkeiten.
Funktionsnamen werden klein_mit_unterstrich geschrieben. Also try_passwords und nicht tryPasswords.
myletters ist eine Konstante, also wird der Name KOMPLETT_GROSS geschrieben. Der Name ist aber nicht so schön, weil das _my_ unnötig ist. Oder gibt es auch your-, her-, his-, und theirletters?
Das _my_ bei myzip ist also auch falsch. Besser: zipfile.
Außerdem solltest du das Zipfile erst in der Funktion öffnen und das with-statement verwenden.
Last but not least: Funktionen können mit return einen Wert zurückgeben. Den musst du verwenden und in deiner Schleife auswerten.
Wobei ich das Auslagern in eine extra Funktion für gefühlt eine Zeile Code etwas übertrieben finde.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 08:45
von __blackjack__
Das ``str.encode(password)`` sollte wohl ``password.encode()`` heissen.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 09:10
von Sirius3
`openzip` ist der falsche Name für die Funktion. Sie sollte `extract_files_with_password` oder so heißen, damit man auch weiß, was sie tut. Dann braucht sie noch einen Rückgabewert, damit Du in der Schleife weißt, ob es geklappt hat, oder nicht.
Nackte excepts niemals verwenden. Fange nur genau die Exception ab, die Du auch erwartest und verarbeiten kannst, hier leider nur RuntimeError, so dass Du eigentlich noch den Inhalt der Exception prüfen mußt, ob auch sicher das falsche Passwort der Grund für die Exception war.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 16:16
von Miscelo
__blackjack__ hat geschrieben: Donnerstag 27. Februar 2020, 08:45
Das ``str.encode(password)`` sollte wohl ``password.encode()`` heissen.
Das Passwort wird im Modul zipFile Bitweise übergeben. Darum muss es hier als string umgewandelt werden.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 16:24
von Jankie
Die eigentliche Syntax für encode() ist:
string.encode()
Die Methode nimmt zwei optionale Parameter entgegen, encoding und errors.
Gerade getestet, kommt das gleiche Ergebnis raus, warum das so ist verstehe ich aber nicht.
Code: Alles auswählen
test_string = "Das ist ein Test"
print(str.encode(test_string))
print(test_string.encode())
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 16:38
von __blackjack__
@Miscelo: Ich weiss was das macht, trotzdem ruft man vorzugsweise (gebundene) Methoden auf dem Objekt auf und nicht die (ungebundene) Methode auf der Klasse mit dem Objekt als Argument. Die Formulieren „als string umgewandelt“ werden ist auch ein bisschen missverständlich: Die Zeichenkette („string“) muss in Bytes umgewandelt werden.
@Jankie: Das erste Argument bei einer (ungebundenen) Methode einer Klasse ist das Objekt auf dem die Methode aufgerufen wird wenn sie auf einem Objekt aufgerufen wird. Also kann man das halt auch über die Klasse aufrufen:
Code: Alles auswählen
instance.method()
# <=>
type(instance).method(instance)
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 16:49
von Miscelo
Jankie hat geschrieben: Donnerstag 27. Februar 2020, 16:24
Die eigentliche Syntax für encode() ist:
string.encode()
Die Methode nimmt zwei optionale Parameter entgegen, encoding und errors.
Gerade getestet, kommt das gleiche Ergebnis raus, warum das so ist verstehe ich aber nicht.
Code: Alles auswählen
test_string = "Das ist ein Test"
print(str.encode(test_string))
print(test_string.encode())
Stimmt schon. Ich habe das irgendwann mal so gelernt und falsch verwendet. Ich werde es mir schnell abgewöhnen. Die Klammer brauch man vielleicht für die Kodierungsmethode.
Code: Alles auswählen
test_string = "Das ist ein Test"
print(test_string.encode('utf-8'))
print(test_string.encode('utf-16'))
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 16:56
von Miscelo
Ich habe eine elegante Lösung zum Beenden der Funktion gefunden " exit(0) " und erkläre es als beendet. Return -Methode geht auch.
Code: Alles auswählen
def openzip(myzip,password):
try:
myzip.extractall("/Pfad/", pwd=password.encode())
print("Das Passwort vom Zipfile ist:" + password)
exit(0)
except Exception:
pass
P.S.
Code: Alles auswählen
test_string = "Das ist ein Test"
print(str.encode(test_string,'utf-16'))
Ist allerdings auch nicht so chic.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 17:07
von __blackjack__
@Miscelo: `sys.exit()` ist an der Stelle alles andere als elegant. Das ist der Hack wenn man keinen ordentlichen Kontrollfluss hinbekommt.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 17:36
von Sirius3
@Miscelo: das ist eine sehr unelegante Methode, weil Du so nichts mehr nach der Schleife machen kannst, zum Beispiel print('Finished') aufrufen, oder die Datei schließen.
Und wie schon geschrieben, die richtige Exception ist hier RuntimeError, nur Exception fängt viel zu viele andere Fehler ab.
Re: Funktion beenden durch Schleifenabbruch
Verfasst: Donnerstag 27. Februar 2020, 17:53
von __blackjack__
Wenn das praxistauglich sein soll, würde ich auch nicht `extractall()` verwenden, denn das entpackt dann ja tatsächlich alle Daten aus dem ZIP obwohl man nur testen will ob ein Passwort passt. Zudem muss nicht jede Datei verschlüsselt sein, und auch die die verschlüsselt sind, nicht alle mit dem gleichen Passwort.
Der `RuntimeError` wegen falschem Passwort wird schon beim öffnen einer Datei im Archiv ausgelöst, das reicht also völlig aus.
Als ersten Schritt könnte man auch ermitteln welche Dateien in dem Archiv überhaupt verschlüsselt sind und sich auf die beschränken, beziehungsweise wenn gar keine Verschlüsselt sind, kann man das Programm ja auch gleich mit einer entsprechenden Meldung beenden statt sinnlos die Kombinationen an unverschlüsselten Dateien durchzuprobieren.