staging.inyokaproject.org

Die Variable und der UnboundLocalError (python3) (Paradoxon?)

Status: Gelöst | Ubuntu-Version: Xubuntu 22.04 (Jammy Jellyfish)
Antworten |

Marakujaa

Anmeldungsdatum:
19. März 2023

Beiträge: 19

Hallo,

Ich hab da mal ne frage; Ab und an schreibe ich aus Spaß am Frust mal das ein oder andere sinnfreie Programm.

Was genau, das tut jetzt erstmal weniger zur sache..

Nu bin ich heut mal auf was anderes gestoßen, eas irgendwie total aus der reihe fällt.

Exception: UnboundLocalError: referenced before assignment

Nun, an sich nix besondere. Vergessen eine Variable zu belegen.. Das Denkste dir! 😲

Sowohl ist die betreffende Variable belegt als auch richtig geschrieben.

Die betreffende Variable ist global verfügbar, weshalb die betreffende Funktion in der sie aufgerufen wird (wird später mehrfach in verschiedenen Funktionen, Klassen, externen Skripts die auf das Skript zugreifen genutzt. Wen das Programm erstmal soweit ist.)

Ich hab die Variable via Copy&Paste da hin kopiert wo sie hin gehört und sicher gestellt, dass sie richtig belegt ist, was ich mir mit einem Testprint (nach ersten auftreten der Exception) hab bestätigen lassen.

Soweit alles Korrekt! Doch akzeptiert Python (3.10.V063L31?) diese verdammte Variable nicht.

Und {[seltsamerweise]}(!!) auch {[an dieser einen stelle nicht]}($@u3r31)

ÜBERALL anders schon (hyääää?)

Ich war schon fast ein Vogelei am Braten. Da hab ich sie aus Frust umbenannt uns es Funktionierte.. (Ja! war korrekt geschrieben) :dasLUSTIGEkopfkraftEMOJYvonDAMALSwelchesHIERfehltUNDichNICHTsuchenMÖCHTE:

Um zum Kern zurück zu kommen; Was löst solch ein verhalten in Python aus?

MFuLG

PS:

Und ähm, könnte mir mal bitte jemand diesen ForumEditor erklären!

Ich bekomm diesen Text ums verrecken nicht richtig Formatiert.. Da braucht man ja bald eine Manpage 😀

Zweizeilen = eine Zeile,

eine Zeile = ohne Zeile

3 Zeilen = mal keine Wirkung, mal 2 Zeilen, mal eine Zeile; ja wat denn jezze

~~ 4-1899999999 Zeilen = eine Zeile; HÄÄÄÄ? und was macht das ding da! Da brat mir einer nen Esel oder den Bürgermeister von Wesel.

*hatNUNaugenkrebs

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

anstatt dein Problem wortreich in etwas schlecht lesbarem Volltextprosa zu beschreiben wäre es deutlich sinnvoller, wenn du den relevanten Code sowie den vollen Stacktrace der Python Fehlermeldung hier posten würdest.

Das Problem ist höchstwahrscheinlich, dass du einen Denkfehler im Gültigkeitsscope von Variablen in Python hast und / oder global falsch verwendest (wobei die Nutzung von global in Python in 99% der Fälle sowieso falsch ist, weil nicht nötig aka schlecht programmiert).

Gruß, noisefloor

Marakujaa

(Themenstarter)

Anmeldungsdatum:
19. März 2023

Beiträge: 19

Guten Morgen,

Das Problem hat sich durch umbenennen der Variable zwischenzeitlich behoben.

Es geht viel mehr um follgende Situation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
## WICHTIGE INFO
# Beispielcode

class datenschreiber():
    def check_exists(var): # Funktioniert
        from os.path import exists
        if exists(var):
           return True
        else:
           return False

    def write():
         # Würde den Rahmen sprängen
         # und hat nix mit dem Problem zu tun!
         pass

def funktion1():
    global beliebige_variable
    beliebige_variable = '/home'

    if datenschreiber.check_exists(beliebige_variable): # funktioniert
        print(beliebige_variable) # funktioniert
    # usw
    # Wir gehen davon aus, dass alles True ist
    # Im falle meines Programmes ist das so und kann keinesfalls anders sein!
    # Unter gar keinen Umständen!

def funktion2():
    # Beispielcode
    # Wie der letzlich ausschaut ist egal, das Problem bleibt das gleiche
    # vollkommen egal wie der code ausschaut!
    print(beliebige_variable) # Exception!! = UnboundLocalError (local variable 'beliebige_variable' referenced before assignment)
    # Kann bekannterweise ja nicht sein.. Wissen wir alle.
    # Trat bei mir in meinem Programm allerdings GENAU SO auf.
    # Warum?

def funktion3():
    print(beliebige_variable) # funktioniert

funktion1()
funktion3() # gehört so
funktion2()

Kann ja eigentlich nicht sein, dass dies NICHT funktioniert.. Die frage ist also, wie kann es sein, dass es erst funktioniert und plöotzlich nicht mehr? (bleibend)

Benenne ich die Variable um, ist das Problem verschwunden. Verwende ich hingegen den ursprünglichen namen ist das Problem wieder da.

Das ist was ich meine..

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

die Klasse datenschreiber ist komplett falsch angelegt so. Da fehlt eigentlich alles inkl. der Verständnis, wie man Klassen in Python nutzt. Z.B. warum sind die Funktionen nicht über self. als Methoden der Klasse deklariert? Gibt es keine init Methode? Gibt es keine Attribute? Und die Klammern () hinter dem Klassennamen sind falsch.

Im späteren Verlauf des Codes greifst du auch direkt auf die Klasse (die eigentlich keine ist) zu statt eine Instanz der Klasse anzulegen.

Wie schon vermutet wird in deinem Code auch global falsch verwendet, im Sinne von das es überhaupt verwendet wird ist hier falsch. Dann passiert nämlich genau das, was dir passiert: der Zustand des Programms ist schwer bis nicht mehr nachvollziehbar. Funktionen kann man Argumente übergeben und Funktionen können Werte zurück geben. Das ist der bessere / richtige Weg, nicht ein globaler Scope einer Variablen. Wenn mehrere Funktionen das brauchen kann man sich auch in eine Klasse packen und den benötigen Wert als Attribut der Klasse ablegen.

os.path ist übrigens veraltet, Stand der Dinge ist das pathlib Modul.

Gruß, noisefloor

Marakujaa

(Themenstarter)

Anmeldungsdatum:
19. März 2023

Beiträge: 19

Der datenschreiber wie ich ihn bisher nutze. Bereitet keine weiteren Probleme..

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
class dw: # Funktioniert so
	# Jup, ist mir klar.. Klassen sind aktuell so ein Thema bei mir.
	# Derzeit noch am Lernen.
	def init(): # Beim Programstart anwählen damit die VARs eingelesen werden.
		global a, ab, an, w, wb, r, rb # zur externen verwendung ala dw.write('/pfad/zur.datei', an, 'String, int oder Binär'). Vereinfacht.
		global ok_R, ok_W, ok_X, ok_RW, ok_RWX, exist, filedir, FILE, DIR # ebenso

		## Funktionen
		# Schreiben
		a		= 'a'				# Erweitern	:	Normal
		ab		= 'ab'				# Erweitern	:	Binär
		an		= 'append_newline'		# Erweitern	:	Neue Zeile
		w		= 'w'				# Schreiben	:	Normal
		wb		= 'wb'				# Schreiben	:	Binär

		# Lesen
		r		= 'r'				# Lesen		:	Normal
		rb		= 'rb'				# Lesen		:	Binär

		# Checks
		ok_R	= 'ok_R'
		ok_W	= 'ok_W'
		ok_X	= 'ok_X'
		ok_RW	= 'ok_RW'
		ok_RWX	= 'OK_RWX'
		exist	= 'exists'
		filedir	= 'filedir'

		# Funktion und Ausgabe/Rückgabe
		FILE		= 'FILE'
		DIR		= 'DIR'
		dw_nowarning 	= False
		return 'AKTIV'

	def check(pfad, io):
		from os import access, R_OK, W_OK, X_OK
		from os.path import exists, isfile, isdir, dirname
		try:
			# Rechteprüfung
			if ((io == ok_R or ok_W == io) or (io == ok_X or ok_RW == io)) or io == ok_RWX:
				if not exists(pfad):
					raise FileNotFoundError
				else:
					if io == ok_R:
						io = access(pfad, R_OK)
					elif io == ok_W:
						io = access(pfad, W_OK)
					elif io == ok_X:
						io = access(pfad, X_OK)
					elif io == ok_RW:
						io = access(pfad, R_OK | W_OK)
					elif io == ok_RWX:
						io = access(pfad, R_OK | W_OK | X_OK)
					else:
						raise RuntimeError
			# Ordner oder Datei
			elif (io == FILE or DIR == io) or io == filedir:
				if io == filedir:
					if isfile(pfad):
						io = FILE
					elif isdir(pfad):
						io = DIR
					else:
						raise RuntimeError
				elif FILE:
					io = isfile(pfad)
				elif DIR:
					io = isdir(pfad)
				else:
					raise RuntimeError
			# Existiert?
			elif io == exist:
				io = exists(pfad)
			else:
				raise ValueError
		except RuntimeError as excep:
			print('dw.check(XXXX, XXXX)\nKritical error in python3! Programm ends here!'); exit()
		except ValueError as excep:
			print('dw.check(XXXX, io)\nUnsupport Value in "io" for checking files: ' + io + '\nCorrect values are: "ok_R", "ok_W", "ok_X", "ok_RW", "ok_RWX"\n')
		except FileNotFoundError as excep:
			print('dw.check(pfad, XXXX)\nNo such file or directory\n' + pfad + '\n')
		else:
			return io
		return False

	def makedir(pfad):
		from os import mkdir
		try:
			mkdir(pfad)
		except (FileExistsError, PermissionError) as excep:
			print('dw.makedir(pfad)\n' + pfad + '\n' + excep.args[1] + '\n'); return False
		else:
			return True

	def write(pfad, io, data):
		from os.path import exists
		# Bei misserfolg: Immer return False, letzer eintrag.
		try: # Hauptoperation
			if (io == r) or (io == rb): # Falsche Funktion
				raise ValueError
			elif ((io == w or wb == io) or (io == a or ab == io)) or (io == an): # Richtige Funktion
				try: # Für ausgabe der internen Warnung
					if (io == an) and (not exists(pfad)):
						raise UserWarning('\nNew line, at the beginning, is removed.\n')
					elif (io == a) and (not exists(pfad)):
						raise UserWarning('\n')
					elif (io == an) and exists(pfad):
						io = a; data = '\n' + data
				except UserWarning as excep:
					if not dw_nowarning:
						print('dw.write(XXXX, io)\nNo such file or directory\nI set write mode to "write" instead "append".' + excep.args[0] + pfad + '\n')
					io = a
				pfad = open(pfad, io)
				io = pfad.write(data)
				pfad.close()
			else:
				raise ValueError
		# Bei Fehlern:
		except (FileNotFoundError, IsADirectoryError, PermissionError) as excep:
			print('dw.write(pfad, XXXX)\n' + pfad + '\n' + excep.args[1] + '\n')
		except TypeError as excep:
			print('dw.write', end='')
			try: # Mehrfach Umwandlung
				try: # Normal
					print('(pfad, XXxx)\n' + pfad.name + '\n' + excep.args[0] + '\n')
				except: # Umwandlung für die Funktion AN
					raise TypeError(excep)
			except: # Umgewandelt
				try:
					# Fehler für die Funktion AN
					print('(pfad, XXXX)\n' + pfad + '\n' + excep.args[0] + '\n')
				except TypeError: # Fehler, wenn kein Pfad angegeben ist.
					print('(pfad, xxXX)\nNo path specified!\n')
		except ValueError as excep:
			print('dw.write(XXXX, io)\nUnsupport Value in "io" for writing files:', io + '\nCorrect values are: "w", "wb, "a", "ab"\n')
		else: # Bei erfolg: return True
			return True
		return False

	def read(pfad, io):
		# Bei misserfolg: Immer Return False, letzer eintrag.
		try: # Hauptoperation
			if ((io == w or wb == io) or (io == a or ab == io)) or (io == an): # Falsche Funktion
				raise ValueError
			elif (io == r) or (io == rb): # Richtige Funktion
				pfad = open(pfad, io)
				io = pfad.read()
				pfad.close()
			else:
				raise ValueError
		# Bei Fehlern:
		except (FileNotFoundError, IsADirectoryError, PermissionError) as excep:
			print('dw.read(pfad, XXXX)\n' + pfad + '\n' + excep.args[1] + '\n')
		except ValueError as excep:
			print('dw.read(XXXX, io)\nUnsupport Value in "io" for reading files:\n' + io + '\nCorrect values are: r, rb\n')
		else: # Bei Erfolg: Rückgabe mit gelesenem wert.
			return io
		return False

	def delete(pfad):
		from os.path import isfile, isdir
		from os import remove, rmdir

		try:
			if isfile(pfad):
				remove(pfad)
			elif isdir(pfad):
				rmdir(pfad)
			else:
				raise FileExistsError
		except (FileExistsError, PermissionError) as excep:
			print('dw.delete(pfad)\n' + pfad + '\n' + excep.args[1] + '\n')
		else:
			return True
		return False

Was das mein eigentliches Problem betriff; Die Klasse in der das Problem auftrat (hier nicht aufgeführt) war nicht korrekt geschrieben.. Zwischenzeitlich funktioniert es.

Anbei; Die Programme die ich schreibe sind für den eigenen gebrauch.. Es ist nicht geplant diese zu veröffentlichen..

Meißt gehts da nur um kleinere dinge, wie beispielsweise eine Konfigurationsdatei fortlaufen anzupassen, sofern eine änderung auftriff. Thunar und größenänderungen sind so so ein fall. Jenachdem wie ich den rechner benutze hab ich dan laufend eine andere Größe. Beende ich Thunar wird die größe der letzten Thunar Instanz in einer Konfigurationsdatei gespeichert. Die kleinen Skripte die ich geschrieben habe sorgend also z.B. dafür, dass die größe beim nächsten start einer Thunar Instanz wieder eine voreingestellte größe entspricht.

Das Programm in dem dieser Datenschreiber eingesetzt wird verwendet dafür eine zusammenstellung von verschiedenen Skripten die durch einen Hauptprozess verwaltet und ausgeführt werden. So wird der Datenschreiber nur ein mal benötigt und alle weiteren Skripte greifen auf diesen Periodisch zu (sofern erforderlich).

Wie und wann das geschieht entscheidet das Hauptprogramm, ohne dabei Threads zu nutzen. Die jeweiligen Module werden dazu nacheinander in einer fest voreingestellten reihenfolge ausgeführt. Sind jetzt nicht gerade skripte die viel Rechenleistung benötigen und währe sicherlich auch mit einem Shellskript zu realisieren.

Allerdings möchte ich die gelegenheit nutzen mich etwas mit Python vertraut zu machen.. Auch da das Programm fortlaufend von mir erweitert wird..

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

die Klasse ist genau so falsch - das ist keine richtige Klasse. Und das global in der init Funktion ist katastrophal falsch.

Und das ist noch viel mehr falsch, z.B. das Importe an den Anfang einer Datei gehören. Und keine nackten try... except verwenden.

Bevor du daran noch irgendwas weiter programmierst solltest du dringend zwei Schritte zurück gehen, dir nochmal den Abschnitt zu Klassen im Grundlagentutorial von Python durchlesen und durcharbeiten. Und wenn du das dann verstanden hast den Code neu schreiben. Ist auch nichts schlimmes, gehört zum Lernen dazu.

Und dann direkt den Rest auch besser machen, wie das pathlib Modul statt os.path benutzen.

Den aktueller Code ist eine Sackgasse, selbst wenn du das Programm rein für die alleine benutzt.

Gruß, noisefloor

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17432

1
2
3
4
5
6
7
class datenschreiber():
    def check_exists(var): # Funktioniert
        from os.path import exists
        if exists(var):
           return True
        else:
           return False

Ich kann ja kein Python, aber wenn das Umbenennen der Variablen den Code heilt, dann ist der 1. Verdacht, dass unzulässige Zeichen im Namen sind - danach sieht es bei var nicht aus - und der 2. Verdacht ist, dass der Name ein reserviertes Schlüsselwort ist. Vielleicht kannst Du den 2. Verdacht prüfen.

Übrigens kann man den Code wahrscheinlich verkürzen zu:

1
2
3
4
class datenschreiber():
    def check_exists (var1): # Funktioniert
        from os.path import exists
        return exists (var1)

Als Nichtpythoniker bin ich da aber nicht sicher. ☺

Marakujaa

(Themenstarter)

Anmeldungsdatum:
19. März 2023

Beiträge: 19

Also..

Ich hab mich jetzt nochmal etwas in die Klassen eingelesen und den Datenschreiber mit ein wenig herumprobieren etwas umgeschrieben.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class datenschreiber:
	def __init__(self):
		while True:
			try:
				if globals_dw == 'AKTIV':
					break
				else:
					raise NameError
			except NameError:
				self.__globals_init_dw()

	def __globals_init_dw(self):
		global a, ab, an, w, wb, r, rb
		global ok_R, ok_W, ok_X, ok_RW, ok_RWX, exist, filedir, FILE, DIR
		global nowarning_dw, globals_dw

		## Funktionen
		# Schreiben
		a		= 'a'				# Erweitern	:	Normal
		ab		= 'ab'				# Erweitern	:	Binär
		an		= 'append_newline'	# Erweitern	:	Neue Zeile
		w		= 'w'				# Schreiben	:	Normal
		wb		= 'wb'				# Schreiben	:	Binär

		# Lesen
		r		= 'r'				# Lesen		:	Normal
		rb		= 'rb'				# Lesen		:	Binär

		# Checks (Nur Prüfen)
		ok_R	= 'ok_R'			# Leserechte
		ok_W	= 'ok_W'			# Schreibrechte
		ok_X	= 'ok_X'			# Ausführen
		ok_RW	= 'ok_RW'			# Lese-/Schreibrechte
		ok_RWX	= 'ok_RWX'			# Alle Rechte
		exist	= 'exists'			# Selbsterklären...
		filedir	= 'filedir'

		# Funktion und Ausgabe/Rückgabe
		FILE	= 'FILE'
		DIR		= 'DIR'

		## Konfiguration
		nowarning_dw = False # Standartmäßig Aktiv (False ist Aktiv!)

		## Für init
		globals_dw = 'AKTIV'
		return

	# Exceptions Ausgaben kann man mit 'nowarning_dw = True/False ab/an stellen. (Terminal)
	def __internal_exception_dw(self, name, excep, data):
		if nowarning_dw:
			return
		else:
			print('FEHLER:\n' + 'dw.' + name + '\n' + excep + '\n' + data + '\n')
			return

	# Prüft einen beliebigen Pfad.
	def check(self, pfad, io):
		from os import access, R_OK, W_OK, X_OK
		from os.path import exists, isfile, isdir, dirname
		try:
			# Rechteprüfung auf Datei/Ordner auf div. Zugriffsrechte
			if ((io == ok_R or ok_W == io) or (io == ok_X or ok_RW == io)) or io == ok_RWX:
				if not exists(pfad):
					raise FileNotFoundError
				else:
					if io == ok_R:
						io = access(pfad, R_OK)
					elif io == ok_W:
						io = access(pfad, W_OK)
					elif io == ok_X:
						io = access(pfad, X_OK)
					elif io == ok_RW:
						io = access(pfad, R_OK | W_OK)
					elif io == ok_RWX:
						io = access(pfad, R_OK | W_OK | X_OK)
					else:
						raise RuntimeError
			# ist es eine Datei/Ordner (True/False oder FILE/DIR, was man braucht.)
			elif (io == FILE or DIR == io) or io == filedir:
				if io == filedir:
					if isfile(pfad):
						io = FILE
					elif isdir(pfad):
						io = DIR
					else:
						raise RuntimeError
				elif FILE:
					io = isfile(pfad)
				elif DIR:
					io = isdir(pfad)
				else:
					raise RuntimeError
			# Existiert der Pfad überhaupt? (True/False)
			elif io == exist:
				io = exists(pfad)
			# Unbekannte Funktion. Gibt einen Fehler aus. :D
			else:
				raise ValueError
		except FileNotFoundError as excep:
			self.__internal_exception_dw('check(pfad, io)', excep.args[1], pfad)
		except ValueError as excep:
			self.__internal_exception_dw('check(pfad, io)', 'Value Error', 'MODE: ' + io)
		except RuntimeError as excep:
			self.__internal_exception_dw('check(pfad, io)', 'Runtime Error', pfad); exit()
		else:
			return io
		return False

	# Ordner erstellen
	def makedir(self, pfad):
		from os import mkdir
		try:
			mkdir(pfad)
		except (FileExistsError, PermissionError) as excep:
			self.__internal_exception_dw('makedir(pfad)' ,excep.args[1], pfad)
		else:
			return True
		return False

	# Dateien Schreiben
	def write(self, pfad, io, data):
		from os.path import exists
		try:
			if (io == r) or (io == rb): # Falsche Funktion
				raise ValueError
			elif ((io == w or wb == io) or (io == a or ab == io)) or (io == an): # Richtige Funktion
				if ((io == an) or (a == io)) and (not exists(pfad)): ## Für ((appena_newline) oder (append)) und (File existiert NICHT)
					io = a
				elif (io == an) and exists(pfad): # für append wen file existiert
					io = a; data = '\n' + data
				datei = open(pfad, io)
				datei.write(data)
				datei.close()
			else:
				raise ValueError
		except (FileNotFoundError, IsADirectoryError, PermissionError) as excep:
			self.__internal_exception_dw('write(pfad, io, data)', excep.args[1], pfad)
		except TypeError as excep:
			self.__internal_exception_dw('write(pfad, io, data)', excep.args[0], 'MODE: ' + io + '\n' + pfad)
		except ValueError:
			self.__internal_exception_dw('write(pfad, io, data)', 'Value Error', 'MODE: ' + io)
		else:
			return True
		return False

	# Dateien Lesen
	def read(self, pfad, io):
		try:
			if ((io == w or wb == io) or (io == a or ab == io)) or (io == an): # Falsche Funktion
				raise ValueError
			elif (io == r) or (io == rb): # Richtige Funktion
				pfad = open(pfad, io)
				io = pfad.read()
				pfad.close()
			else:
				raise ValueError
		except (FileNotFoundError, IsADirectoryError, PermissionError) as excep:
			self.__internal_exception_dw('read(pfad, io)', excep.args[1], pfad)
		except ValueError as excep:
			self.__internal_exception_dw('read(pfad, io)', excep.args[1], pfad))
		else:
			return io
		return False

	# Datei/Ordner Löschen (Wählt automatisch, anhand des Pfades)
	def delete(self, pfad):
		from os.path import isfile, isdir
		from os import remove, rmdir
		try:
			if isfile(pfad):
				remove(pfad)
			elif isdir(pfad):
				rmdir(pfad)
			else:
				raise FileExistsError
		except (FileExistsError, PermissionError) as excep:
			self.__internal_exception_dw('delete(pfad)', excep.args[1], pfad))
		else:
			return True
		return False

datenschreiber() # Initzeile 1
dw = datenschreiber() # Initzeile 2

@user_unknown Den Code den Du da von mir hast war ein Beispielcode. Der eigentliche Datenschreiber (neu) ist dieses (Vergleichsweise) Monster hier im Codeblock. Da ist die verkürzung mit drin.

Der fehler auf den ich da zuletzt gestoßen bin, entstand nicht im Datenschreiber. Es ging um eine Variable die an einer anderen stelle im Code durch eine Funktion vordefiniert war, als Global festgelegt war (da sie an verschiedenen stellen im Skript verwendet werden sollte. Das übergeb der betreffenden Variable ließ sich zu jener zeit nicht anders verwirklichen, da ich die Klassen in Python teilweise bzw ganz falsch verwendet habe).

Übung macht den Meister.. Ich bin kein Meister, also muss ich durch Hinfallen und wieder Aufstehen Lernen wie es fnuktioniert.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

das ist immer noch furchtbar falsch. globals_dw muss an der Stelle doch zu einem NameError führen, weil es dort nicht definiert sein kann, jedenfalls nicht zu dem Zeitpunkt. Und global in einer Klasse verwenden ist in 99,99% der Fälle falsch, so auch hier. Das möchtest du alles zu Attributen der Klasse mache.

Zeile 183 im letzten Post ist sinnlos, weil die erzeugte Instanz an nichts gebunden wird, d.h. die ist direkt wieder weg. Methodennamen mit zwei Unterstrichen __ beginnen zu lassen ist nicht nötig, weil du ziemlich sicher keine Namenskonflikte hast. Die Importe stehen immer noch an der falschen Stelle. Eingerückt wird bei Python per Konvention mit 4 Leerzeichen, nicht mit 8.

Gruß, noiseflor

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17432

Marakujaa schrieb:

@user_unknown Den Code den Du da von mir hast war ein Beispielcode.

Tja. Eine gute Idee ist es, den Code, der nicht funktioniert, so radikal einzukürzen, dass nur das absolut notwendige Minimum noch drin ist, um den Fehler zu reproduzieren, aber eben genug, dass man sich das in die REPL oder den Editor kopieren kann, und bei sich den Fehler reproduziert.

Reproduziert man den Fehler nicht liegt es wohl an eingebetteten Bibliotheken, unterschiedlichen Versionen oder dem Aufruf des Programms.

Sehr oft findet man auf die Weise seinen Fehler selbst, denn man kürzt Dinge weg, die für den Fehler nicht bedeutsam sind - denkt man - und dann ist der Fehler plötzlich weg und man stellt fest, dass die Annahme, was gesichert ist, falsch war.

Oder man kann den Fehler stärker eingrenzen als ursprünglich gedacht und lernt dabei etwas wichtiges, um ihn zu beseitigen.

Marakujaa

(Themenstarter)

Anmeldungsdatum:
19. März 2023

Beiträge: 19

noisefloor Schrieb: Eingerückt wird bei Python per Konvention mit 4 Leerzeichen, nicht mit 8.

Das liegt hier am Codeblock der Tabs mit 8 anstatt 4 Zeilen einrückt. Ich hab den Code so wie er da steht aus dem Editor eingefügt.

Also ein Problem des Forum-Editors!

–- –- –- –- –-

noisefloor Meinte: globals_dw muss an der Stelle doch zu einem NameError führen

Tut es auch. Die Exception wird abgefangen, was dann __globals_init_dw aufruft um die globalen Variablen zu laden und es anschließend erneut zu versuchen, was dann auch funktioniert.

–- –- –- –- –-

noisefloor Ermahnte: Zeile 183 im letzten Post ist sinnlos, weil die erzeugte Instanz an nichts gebunden wird, d.h. die ist direkt wieder weg.

Zeile 183 ist tatsächlich überflüssig. Seltsamerweise hat es zuletzt ohne diese nicht funktioniert, was verwirrend ist.

–- –- –- –- –-

noisefloor Fragte(???): Das möchtest du alles zu Attributen der Klasse mache.

Was für Attribute?

'_datenschreiber__globals_init_dw'
'_datenschreiber__internal_exception_dw'
'check'
'delete'
'makedir'
'read'
'write'

und

'__class__'
'__delattr__'
'__dict__'
'__dir__'
'__doc__'
'__eq__'
'__format__'
'__ge__'
'__getattribute__'
'__gt__'
'__hash__'
'__init__'
'__init_subclass__'
'__le__'
'__lt__'
'__module__'
'__ne__'
'__new__'
'__reduce__'
'__reduce_ex__'
'__repr__'
'__setattr__'
'__sizeof__'
'__str__'
'__subclasshook__'
'__weakref__'

oder was genau meinst du?

–- –- –- –- –-

noisefloor Wies darauf hin: Methodennamen mit zwei Unterstrichen __ beginnen zu lassen ist nicht nötig, weil du ziemlich sicher keine Namenskonflikte hast.

Das ist richtig. Damit möchte ich bewirken, dass diese Methoden des Datenschreibers (vorerst) extern nicht aufrufbar sind.

–- –- –- –- –-

EDIT:

Vernünftig Formatiert, überflüssiges entfernt. Generell etwas überarbeitet. Augenkrebs muss nicht sein.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

Also ein Problem des Forum-Editors!

Nope, weil eingerückt wird per Konvention mit 4 Leerzeichen, nicht mit Tabs. Funktioniert zwar, gilt aber als schlechter Stil. Du solltest deinen Editor so einstellen, dass beim Schreiben von Python-Code beim Druck auf die Tab-Taste vier Leerzeichen eingefügt werden.

Was für Attribute?

Wenn du das (noch) nicht weißt: drei Schritte zurück und den Abschnitt zu Klassen im offiziellen Python-Tutorial durcharbeiten. Du kannst keine Klasse schreiben, ohne verstanden zu haben, was Attribute und Methoden einer Klasse sind. Das sind absolute Grundlagen dafür. Link 🇬🇧

Tut es auch. Die Exception wird abgefangen, was dann __globals_init_dw aufruft um die globalen Variablen zu laden und es anschließend erneut zu versuchen, was dann auch funktioniert.

Mal abgesehen davon, dass der Code so sowieso falsch ist: dann solltest du dir vielleicht mal Gedanken über die Logik deines Programmflusses machen und das ganze umdrehen?

Das ist richtig. Damit möchte ich bewirken, dass diese Methoden des Datenschreibers (vorerst) extern nicht aufrufbar sind.

Verständnisfehler deinerseits: es gibt in Python keine privaten Attribute oder Methoden. _Alles_ ist von extern aufrufbar, egal ob ohne, mit einem oder mit zwei führenden Unterstrichen. Bei zwei führenden Unterstrichen ändert sich nur das "wie" das Aufrufs.

Gruß, noisefloor

Marakujaa

(Themenstarter)

Anmeldungsdatum:
19. März 2023

Beiträge: 19

Nope, weil eingerückt wird per Konvention mit 4 Leerzeichen, nicht mit Tabs. Funktioniert zwar, gilt aber als schlechter Stil. Du solltest deinen Editor so einstellen, dass beim Schreiben von Python-Code beim Druck auf die Tab-Taste vier Leerzeichen eingefügt werden.

Ob schlechter Stil hin oder her..

Mit leerzeichen bekomme ich durchgehend Probleme mit der Einrückung und andauernd teilweise hunderte zeilen neu einzurücken, hab ich ganz schlicht und ergreifend keine lust mehr drauf. Frag nicht wie ich das schaffe, ich weiß es selbst nicht.

Wenn du das (noch) nicht weißt: drei Schritte zurück und den Abschnitt zu Klassen im offiziellen Python-Tutorial durcharbeiten. Du kannst keine Klasse schreiben, ohne verstanden zu haben, was Attribute und Methoden einer Klasse sind. Das sind absolute Grundlagen dafür. Link 🇬🇧

Was ist denn daran Falsch? Dies sind Variablen, welche global gesetzt werden, damit sie global überhaupt erstmal auffindbar sind oder denkst Du diese Variablen werden ausschließlich nur im Datenschreiber verwendet. Falls ja, dann irrst Du dich.

Damit:

1
dw.write('/ein/beliebiger/pfad', wb, b'beliebige Daten')

Funtioniert müssen diese Variablen auch global verfügbar sein.

Andernfals erhalte ich einen Traceback.

1
2
3
4
5
6
class test:
    def vars(self):
        test1 = 'test'

t = test()
print(test1)
1
2
3
4
Traceback (most recent call last):
  File "//home/marakujaa/python/tests/test6.py", line 9, in <module>
    print(test1)
NameError: name 'test1' is not defined. Did you mean: 'test'?

Im grunde ist es egal wie Du versuchst 'test1' aufzurufen, es führt jedesmal zu einem NameError oder einem ArtibutError. Es gibt derzeit zwei mir bekannte möglichkeiten das Problem zu lösen;

1.)

1
2
3
4
5
6
7
test1 = 'test1'

class test:
    def prints(self):
        print(test1)

t = test(); t.prints()
## Ausgabe entspricht:
test1
test2

oder 2.)

1
2
3
4
5
6
7
class test:
    def vars(self):
        global test1
        test1 = 'test'

t = test()
print(test1)

Möchte ich nun test1 noch in der klasse/funktion verändern und die veränderung soll global verfügbar sein, da der darin enthaltene Wert von der klasse selbst oder einer anderen funktion zu einem späteren Zeitpunkt verwendet wird, muss ich das ganze entweder so;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
test1 = 'test1'

class test:
    def vars(wert):
        global test1
        test1 = wert

    def prints(self):
        print(test1)

t = test(); t.prints(); t.vars('test2'); t.prints()

oder so;

1
2
3
4
5
6
7
8
class test:
    def vars(self, wert):
        global test1
        test1 = wert

t = test()
print(test1)
t.vars('test2')

schreiben. Andernfalls ist der wert nähmlich entweder weg oder nicht verfügbar.

Global wird hier also verwendet um die Variable 'test1' global verfügbar zu machen. Nicht wirklich anders verhält es sich mit dem Datenschreiber.

Global wird hier dazu genutzt um die variablen des datenschreibers wie z.B. 'a', 'ab', 'w', 'wb', usw, dem globalen Namensraum zuzuweisen um sicher zu stellen, dass diese Variablen auch gloabl und nicht 'nur' im Datenschreiber verfügbar sind.

1
2
dw.write('/pfad/zur.datei', wb, b'Das sind die daten.')
# Darum gehts:              ^^

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 12527

Marakujaa schrieb:

Mit leerzeichen bekomme ich durchgehend Probleme mit der Einrückung und andauernd teilweise hunderte zeilen neu einzurücken, hab ich ganz schlicht und ergreifend keine lust mehr drauf. Frag nicht wie ich das schaffe, ich weiß es selbst nicht.

Es gibt Programme, die die passende Einrückung automatisch erzeugen. Ansonsten sollten das alle modernen Editoren und selbst vim hinbekommen.

Edit: hatte das Zitat vergessen.

noisefloor Team-Icon

Ehemaliger
Avatar von noisefloor

Anmeldungsdatum:
6. Juni 2006

Beiträge: 28316

Hallo,

du scheiterst programmiertechnisch gerade krass an der selber, weil du dich auf nichts einlässt und unbedingt das umsetzen willst, wie _du_ es für richtig hältst. Oder anders: du programmierst gegen die Sprache, weil du die Grundkonzepte schlicht nicht akzeptierst bzw. lernen willst.

Kann man machen, geht aber selbst mittelfristig nicht gut. Darum hast du auch Probleme, siehe Ausgangspost.

Gruß, noisefloor

Antworten |