Probleme beim importieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MightyM
User
Beiträge: 11
Registriert: Samstag 10. März 2012, 19:06

Samstag 10. März 2012, 19:45

Hey all,
Ich stehe vor einem kleinen, lästigen, mir recht ärgerlichen Problem! Und zwar importiere ich von der Klasse InputProof() die Klasse Configuration(), bekomme aber beim Aufruf eines Attributes (Configuration.WorkPath) eben dieser Klasse die Fehlermeldung das der Klassenname nicht definiert ist (beim importieren selbst gibt es keine Fehlermeldung).
Und das ganz komische ist, dass es vorher noch funktionierte bis ich etwas grössere Änderungen an der Configuration()-Klasse vorgenommen habe (jedoch weder etwas am Klassennamen noch am Dateinamen welche selbstverständlich beide genau gleich heissen)

Configuration()-Code:

Code: Alles auswählen

import os
from ControlPanel import *
from InputProof import *
from shutil import copy

class Configuration():
       ConfigurationPath = "C:\Configuration"
       ConfigurationFileName = "configuration.txt"
       WorkPath = "C:\Dictonarys"
...
InputProof()-Code:

Code: Alles auswählen

from Configuration import *
from ControlPanel import *
from os import listdir

class InputProof():
       WorkPath = Configuration().WorkPath
...
Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "PFAD\InputProof.py", line 9, in InputProof 
      WorkPath = Configuration().workpath
NameError: name 'Configuration' is not defined
Und irgendwie habe ich so das dumme Gefühl das es ein kleiner Fehler ist welchen ich die ganze Zeit nicht bemerke! :roll:

Gruss MightyM
Benutzeravatar
Hyperion
Moderator
Beiträge: 7477
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Samstag 10. März 2012, 20:07

- Hui... also erst einmal: Sternchen-Importe sind böse :twisted:

- Als nächstes: Dis ist die Ineffizienz bewusst? Du erzeugst immer ein neues ``Configuration``-Objekt, nur um auf ein Klassen(!)-Attribut zuzugreifen. Das willst Du sicher nicht... so geht es doch auch:

Code: Alles auswählen

In [1]: class Configuration(object):
   ...:     path = r"foo/bar"
   ...:
   ...:

In [2]: Configuration.path
Out[2]: 'foo/bar'
- Bei Pfaden solltest Du RawStrings benutzen - sonst kann es zu ungewollten Escape-Sequenzen kommen.

- Bei Python 2.x sollten Klassen von ``object`` erben.

- Wieso es zu dem Fehler kommt, ist mir bei den Infos schleierhaft. Hast Du mal die '*.pyc'-Dateien alle gelöscht? Evtl. hattest Du da mal einen falschen Namen drin stehen, der noch nicht aktualisiert wurde? Ansonsten schaue Dir noch mal die exakte Schreibweise an - stimmt die in Deinem Code wirklich überein?

Als letztes: Wieso muss es eigentlich eine Klasse sein? Damit abstrahierst Du im Moment zwei Mal... einmal auf Objekt und dann noch mal auf Namensraumebene in Deinem Configuration-Modul. Steht denn da noch mehr drin? Ansonsten: Weg mit der Klasse :-D
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

Samstag 10. März 2012, 20:08

@MightyM: Du hast zwei Module die sich gegenseitig importieren. Das ist keine gute Idee, weil dann eben genau so etwas passiert — zu dem Zeitpunkt wo ein Name aus dem anderen Modul verwendet werden soll, ist das vor dem importieren noch nicht weit genug ausgeführt worden, dass der Name auch definiert ist. Vermeide zirkuläre Importe, zum Beispiel in dem die gemeinsame Abhängigkeit in ein eigenes Modul ausgelagert wird.

Davon abgesehen sieht der Code deutlich komplizierter aus als er sein müsste. Warum ist `Configuration` eine Klasse? Warum erstellst Du davon ein Exemplar, nur um auf *Klassen*attribute zuzugreifen. Das macht beides gar keinen Sinn. Für Konfigurationsdaten ist es nicht unüblich einfach ein Modul zu verwenden und dort Namen an Werte zu binden. Und das Konfigurationsmodul sollte *selbst* nichts von der Programmlogik importieren, denn genau dann bekommt man zwangsläufig wieder wechselseitige Abhängigkeiten, die man nicht haben möchte.

Sternchenimporte sollte man vermeiden. Damit wird es schwerer nachzuvollziehen welche Namen aus welchem Modul kommen und oft müllt man sich damit den Namensraum zu. Beides, wechselseitige Abhängigkeiten und Sternchenimporte, stellen das Konzept von Modulen in Frage. Falls Du eine Klasse pro Datei haben solltest, wonach das so ein bisschen aussieht, dann ist das ein weiterer Anhaltspunkt, dass Du Module in Python ignorierst.

Wegen der Namensgebung solltest Du mal einen Blick in PEP 8 -- Style Guide for Python Code werfen.
MightyM
User
Beiträge: 11
Registriert: Samstag 10. März 2012, 19:06

Samstag 10. März 2012, 21:45

Danke den beiden Antworten erstmal.

Dummerweise kann ich zurzeit nicht das ganze Programm reinstellen, da es auf dem Arbeitslaptop liegt, an welchen ich - wegen Virenschutz - kein externes Gerät anschliessen kann. Denn nein das war nicht das ganze Programm. Vielleicht ist es doch noch besser etwas zu der Funktion zu sagen:

Die Idee war das zufällige Abfragen von Fremdwörtern um diese schneller zu lernen, als wenn man sie von Hand schreibt. D.h. es werden beliebig viele Wortpaare in eine .txt geschrieben und die 2 Wörter von jedem Wortpaar jeweils mit einem Doppelpunkt verbunden --> hallo:hello Wie_gehts?:How_are_you? ...

Da ich mit der Objektorientierten Programmierung noch ein bisschen kämpfe, habe ich - wie es mir gesagt wurde - einfach mal "objektiv" klassen erstellt.
D.h. ich habe...
-ein "Editor"; hier werden die Abfrageübungen erstellt und falls nötig im nachhinein bearbeitet
-dann gibt es den "Player"; er fragt dich mit bestehenden Übungen ab
-um möglichst alle Fehler abzufangen hab ich noch den "InputPrüfer"; er schaut das man den gewünschten datentyp eingibt, ob die Eingabe (vorallem auf Files oder Pfade bezogen) auch gültig sind, oder das man nur zahlen in einer gewissen range eingeben kann. Neu hab ich noch die Funktion (welche ich wegen diesem Fehler bisher noch nicht testen konnte) hinzugefügt die bei jeder Eingabe prüft ob die Eingabe exit ist; wenn ja soll man zurück ins Hauptmenü Gelangen. Das ist jedoch sehr "schlampig" da ich einfach jedesmal die klasse ControlPanel() aufrufe, mir viel aber keine andere Vriante ein.
-das ControlPanel ist dann das Hauptmenü, also der Startpunkt. Es macht nichts anderes als auf die anderen Klassen zu verweisen
-Und dann eben die Configuration-Klasse. Sie dient nur als Schnittstelle zwischen Programm und Conf-txt. D.h. sie besitzt alle funktionen um die Einstellungen zu ändern (Gross-/Kleinschreibung Ein/Aus, Forwärts/Rückwärts fragen, den Pfad wo die Übungen liegen und der Pfad der eigendlichen Conf-Datei) Als erstes sollte immer diese Klasse aufgerufen werden, welche die Conf-Datei einliest und falls sie noch nicht vorhanden ist erstellt. Da man die einstellungen auch ändern kann musste ich bei der Conf-Klasse den InputProofer importieren um die Eingaben zu prüfen.

Nun ich habe ich das doofe Gefühl das ich auf der völlig falschen Spur bin. Denn wenn ich es mir genauer überlege könnte man alle Funktionen in eine einzige Klasse zusammenfügen, es würde sich nichts widersprechen. Eigenschaften hat nur die Conf-Klasse, alle anderen klassen kopieren die WorkPath-Eigenschaft von der Conf-Klasse (völlig überflüssig wenn ich es mir genau überlebe :roll: )

Ich sehe keine Vorgaben/Regeln im objektorientierten Programmieren was es mir extrem erschwert, auf der richtigen Spur zu bleiben, denn Python gibt nicht mehr einfach eine Fehlermeldung aus wenn ich etwas falsches - oder meistens überflüssiges mache. Und bisher hat auch alles funktioniert, was mich dazu motivierte das Programm weiter auszubauen und zu perfektionieren nun stecken ca. 8-10h Arbeit und 500 Zeilen Code im Programm :lol:

Nun denn ich werd mich warscheinlich noch etwas mit Lesestoff eindecken müssen ^^

Gruss
Benutzeravatar
pillmuncher
User
Beiträge: 1140
Registriert: Samstag 21. März 2009, 22:59
Wohnort: München

Sonntag 11. März 2012, 04:02

MightyM hat geschrieben:Ich sehe keine Vorgaben/Regeln im objektorientierten Programmieren
Als Einstieg in OO empfehle ich Head First: Design Patterns vom O'Reilley-Verlag. Zwar ist aller Code in Java, aber man hat sich bemüht, ihn so einfach verständlich wie möglich zu halten. Ihn nach Python zu übertragen dürfte nicht schwer fallen. Das Buch gibt es auch auf Deutsch, aber ich weiß nicht, wie gelungen die Übersetzung ist. Deswegen der Link auf die englische Version, die ich kenne.

Wenn du von Objekt-Orientierung wirklich noch keine Ahnung hast (also nicht weißt, ob, wann und wie du welche Klasse programmieren solltest), dann bietet dieses Buch immerhin diesen Vorteil, dass du hier die Design-Prinzipien der Objekt-Orientierung in Aktion erleben kannst. Diese Prinzipien werden im Buch explizit benannt und erklärt und zu den Patterns in Beziehung gesetzt, ganz anders als in der Design-Patterns-Bibel, wo dies höchstens nebenbei geschieht und dann nur recht unstrukturiert. Ebenso wie in jedem anderen mir bekannten Buch zum Thema Einführung in die Objekt-Orientierung. Meistens werden dort nur die basalen Konstrukte erklärt, aber die Beispiele zeigen regelmäßig bloß, wie die Daten-Attribute von Objekten mittels Methoden manipuliert werden, ggf. polymorph via überschriebener Methoden in Sub-Klassen, aber keines zeigt ein halbwegs realistisches Szenario auf, aus dem ersichtlich würde, warum man derartige Dinge tun sollte. Allerdings kenne ich nicht alle Bücher zu diesem Thema. Vielleicht gibt es ja solch ein Wunderbuch.

Oder aber dir hilft dieser Beitrag aus einem alten Thread.

Gruß,
Mick.
In specifications, Murphy's Law supersedes Ohm's.
MightyM
User
Beiträge: 11
Registriert: Samstag 10. März 2012, 19:06

Sonntag 11. März 2012, 13:40

@ Mick,
Okay Danke für deine Empfehlung, ich werde mir das mal genauer anschauen.
Antworten