Forum Thread
  Posts  
[Python] for loop Error (Forums : Coding & Scripting : [Python] for loop Error) Locked
Thread Options
Oct 4 2014 Anchor

Good Day,
I´ve a big Problem with my loop. It runs it only one time and then the loop stops.
Here is my code.

#-----------------------------------------------------------------------------------------------------------------------------------
# File: check_version.py
# Beschreibung: Erstellt von allen Datein im Game Ordner einen MD5 Hash und vergleicht diese mit den auf dem Server hinterlegten
# Datum: 16.09.2014
# Programmierer: Daniel
# Externer Code: def digest von http://www.computerbase.de/forum/showthread.php?t=1175346
#-----------------------------------------------------------------------------------------------------------------------------------
import os
import sys
import hashlib
import urllib
import BWPersonality

UpdatetServerUrl = "http://80.246.63.50/Update/checksum.md5"
HashStatus = True
path = ""

class versions_check():	

	def __init__(self):
		global UpdatetServer
		UpdatetServer = urllib.urlopen( UpdatetServerUrl )
		path = os.path.dirname(os.path.abspath(sys.argv[0]))

	def digest(self, file):
		'''digest takes 1 file as argument and returns its md5 sum
		Source code taken from StackOverflow
		'''
		
		md5 = hashlib.md5()
		with open(file,'rb') as f: 
			for chunk in iter(lambda: f.read(8192), b''): 
				md5.update(chunk)
		return(md5.hexdigest())
		
	def createHashList(self):
		global path
		for path, _, filenames in os.walk(path):
			for file in filenames:
				global HashStatus
				while HashStatus == True:
					filepath = os.path.join(path,file)
					md5sum = self.digest(filepath)
					
					for line in UpdatetServer:
						if md5sum in line:
							print(line)
							HashStatus = True
						else:
							HashStatus =False

		
		print"Fertig"
#		BWPersonality.startUpWindow()
				

	
# check_version.py

The code should create a MD5 Hash from a Folder and all Files and subfolders there. And then check if the MD5 Hash is in a list on a Server.

Many thanks for your help.
Best Regards

Dragonlord
O
N
L
I
N
E
Dragonlord Linux-Dragon of quick wit and sharp tongue
Oct 4 2014 Anchor

Also als erstes solltest du einmal den Code general umschreiben. Da wird "class" benutzt aber dann globale Variablen mit "global" quer durch die Pampa. Ausserdem ist es eine schlechte Idee "path" als globale Variable zu definieren, in einem os.walk loop als Iterator zu verwenden und dann auch noch gleich als Eingabe für die rekursive os.walk Funktion. Mach zuerst einmal die globalen Variabeln weg. Die werden dir beständig in den Arsch beissen, egal was du tust.

Jetzt zum eigentlichen Problem. Die Schleife bricht ab, wenn HashStatus auf False wechselt. Ich versteh jetzt nicht, was dieser Code eigentlich genau machen soll, aber er wird bei der ersten Schleife aufgeben, falls der Code nicht in der Liste vorhanden ist. Wenn ich die richtig verstanden hasst, willst du aber zuerst all hashes rechnen und erst dann vergleichen. Hier wird nach jedem berechneten Hash verglichen und die Übung beim ersten Eintrag abgebrochen, der nicht in der Liste ist.

Aber vielleicht versteh ich auch nicht das Problem, das du hier versuchst zu lösen, denn der Code ist leder sehr nicht-Pythonisch.

Oct 4 2014 Anchor

Ach du schande, da habe ich einige verbockt beim code :-(
Ich muss ja mit global arbeiten, da wenn ich in CreateHashlist einsteige den fehler "referenced before assignment" bekomme.
Wenn ich auf die global verzichte muss ich von der init aus auf die CreateHashlist weiter gehen.

Das Problem ist, es wird nur von einer Datei ein Hashwert erstellt.
Dieser wird mit der ganzen hinterlegten liste verglichen (hier fehlen noch welche break, da er die ganze liste trotz eine True durchläuft)
Dann beendet er die Funktion ohne von den restlichen Datein im Ordner den Hash zu erstellen.

Dragonlord
O
N
L
I
N
E
Dragonlord Linux-Dragon of quick wit and sharp tongue
Oct 4 2014 Anchor

Vergiss die globalen Variablen. Du hast eine Klasse, also eine Instanz. Der kannst du Variablen zuweisen, welche du für das bearbeiten brauchst. Die anderen Variablen sind sowiso nur methoden-lokale Variablen. UpdatetServer und path zum Beispiel sind Eigenschaften des Objektes. Die kannst du der Objekt-Instanz beim Init einfach zuweisen und später brauchen, so in der Art hier:

class VersionChecker:
   def __init__(self):
      # create instance variables using self.VARNAME = VALUE
      self.updatetServer = urllib.urlopen( UpdatetServerUrl )
      self.searchPath = os.path.dirname( os.path.abspath( sys.argv[0] ) )
   ...
   def createHashList(self):
      # method local variable, works throughout this entire method
      hashStatus = True
      # access instance variables with self.VARNAME
      for curDir, scanDirs, filenames in os.walk( self.searchPath ):
         # no need for '== True', it's the default if nothing is written explicitly
         while hashStatus:
            ...
            # here too access the instance variable instead of lumping it into globals
            for line in self.updatetServer:

# the way to run it
a = VersionChecker()
a.createHashList()

Der Rest solltest du damit hinbekommen, denn du hast die Lösung schon selber gesehen. Wegen dem fehlenden break müsste die richtige Zeile die letzte sein, sonst wird HashStatus auf False enden, da nach der richtigen Zeile falsche folgen werden.

Edited by: Dragonlord

Oct 5 2014 Anchor

Ich habe trotzdem noch das Problem, das die erste schleife immer nur einmal ausgeführt wird.
Und wenn ich bei der zweiten schleife ein True habe, springt er nicht mehr auf die erste schleife.

Oder ist es besser wenn ich zuerst alle Hash erstelle und in eine Liste speichere. Und dann beide listen vergleiche?

Dragonlord
O
N
L
I
N
E
Dragonlord Linux-Dragon of quick wit and sharp tongue
Oct 5 2014 Anchor

Es kommt drauf an, was das Ziel der Übung ist. Wenn es nur darum geht zu prüfen, ob alle Dateien in der Liste sind, dann reicht die Version hier, wo beim ersten Fehler ein False zurück geliefert wird. Übrigens ist die folgende Version hier weniger Fehleranfällig:

self.hashStatus = ( [ l in self.updateServer if md5sum in l ] != None )

Oder wenn ein print benötigt wird:

found = [ l in self.updateServer if md5sum in l ]
print( found[0] if found else "Not found" )
self.hashStatus = ( found != None )

Edited by: Dragonlord

Reply to thread
click to sign in and post

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.