Seite 1 von 1

Kreuzweises Importieren von Modulen

Verfasst: Montag 22. Juni 2009, 21:49
von cui
Hallo.

Ich habe folgende zwei Beispielscripte:

Code: Alles auswählen

### eins.py
from zwei import C

class A:
    def __init__(self):
        C()

class B:
    pass



### zwei.py
from eins import B

class C (B):
    pass
So geht das ganze schonmal nicht:

Code: Alles auswählen

Traceback (most recent call last):
  File "eins.py", line 1, in <module>
    from zwei import C
  File "/home/cui/projects/bjs-prog/zwei.py", line 1, in <module>
    from eins import B
  File "/home/cui/projects/bjs-prog/eins.py", line 1, in <module>
    from zwei import C
ImportError: cannot import name C
Wenn ich jetz in zwei.py den import auskommentiere dann gehts aber auch nicht:

Code: Alles auswählen

Traceback (most recent call last):
  File "eins.py", line 1, in <module>
    from zwei import C
  File "/home/cui/projects/bjs-prog/zwei.py", line 3, in <module>
    class C (B):
NameError: name 'B' is not defined
Was soll ich jetzt tun?

lg,
cui.

Verfasst: Montag 22. Juni 2009, 21:59
von Leonidas
Hallo cui, willkommen im Forum,

Steck die Klassen doch einfach in ein Modul.

Verfasst: Montag 22. Juni 2009, 22:01
von BlackJack
@cui: Du solltest einfach keine Module mit gegenseitigen Abhängigkeiten schreiben. Entweder ist das ein Zeichen, dass alles in ein Modul gehört, oder Du solltest Sachen, die beide Module benötigen, in ein drittes Modul auslagern.

Verfasst: Montag 22. Juni 2009, 22:21
von cui
Ok, aber es ist doch auch ein schlechter Stil, meinetwegen 10 Klassen alle in eine Datei zu schreiben... Also ich jedenfalls finds unübersichtlich.. Außerdem wird die Arbeit als Team deutlich erschwert wenn alles in einer Datei liegt...

Oder gibt es eine Möglichkeit, ein Modul in mehrere Dateien auf zu spalten?

Verfasst: Montag 22. Juni 2009, 22:25
von cofi
Datei = Modul.

Nein, es ist kein schlechter Stil zusammenzupacken, was zusammengehört.

Wie wird denn die Teamarbeit behindert? Im Zeitalter von Versionskontrollen und Diff-/Mergetools kann das doch nicht dein ernst sein?

Verfasst: Montag 22. Juni 2009, 22:28
von cui
Ok, es handelt sich um eine kleines Schülerprojekt, und außer mir und vllt noch 1 oder 2 hat da keiner eine Ahnung was Bazaar oder Subversion ist. Python dagegen wurde sehr wohl behandelt.

Abgesehen davon:
Ich persönlich jedenfalls finde eine Datei mit sagen wir 2000 Zeilen Code (es sind genau 7 Klassen die untereinander referenzieren) unübersichtlich.. Ich weiß nicht wies euch geht.

In anderen modernen Hochsprachen wie Java, C# ist derartig triviales wie Strukturierung nach Klassen doch auch möglich und vorallem normal..

Verfasst: Montag 22. Juni 2009, 22:32
von cofi
Dann nehmt euch die 10 Minuten die es braucht sich mit Mercurial bekannt zu machen, geht zu bitbucket.org und die Zusammenarbeit ist kein Problem.

Mercurial lässt sich natürlich mit jeder anderen (D)VCS-Software austauschen und bitbucket.org mit jedem anderen Hoster.

Wenn ihr so große Implementationen mit so großen Abhängigkeiten habt und ihr es selbst als übersichtlich empfindet, solltet ihr euch mal den Code genauer anschauen und überarbeiten.

Verfasst: Montag 22. Juni 2009, 22:35
von cui
Na ja, wenn du die Tabelle für das Deutsche Sportabzeichen abtippen musst (mit welchen Weiten man besteht wenn man z.B. 15 Jahre und meinetwegen männlich ist), dann sind das shcon alleine mind. 300 Zeilen trivialer Code...

Verfasst: Montag 22. Juni 2009, 22:38
von cofi
Das sind aber 300 Zeilen Code, die eigentlich kein Code sind, sondern Daten.
Da bietet sich das CSV-Modul an.

Und wenn man das fest in ein Programm verdrahtet ist das durchaus schlechter Stil ;)

Verfasst: Montag 22. Juni 2009, 22:48
von cui
Da stimme ich dir prinzipiell zu, es wäre vielleicht am Klügsten gewesen. Aber nun steht es leider aufgrund meines Planungsfehlers schon so da und ich habe keine Lust eigentlich mir die Arbeit mit dem Abschreiben nochmal zu machen.
... Wenn du die Tabelle nochmal abschreiben willst und einen Parser dafür, bitte gerne, wir wären dir dankbar!

Sagen wir einfach das Projekt steht bereits zur Hälfte, und nochmal alles um zu designen wäre uns zu viel Aufwand. Nächstes mal planen wir das dann besser, da wir nun ja wissen, dass sich referenzierende Klassen in Python schnell zu Schwierigkeiten führen können; das hatte ich einfach nicht bedacht beim Entwurf, mein Fehler.

Also um zur Frage zurück zu kommen: Gibt es nun irgendeine andere Möglichkeit, als alles in eine Datei zu packen, oder müssen wir selber schaun wie wir nun damit umgehen?

lg,
cui

Verfasst: Montag 22. Juni 2009, 22:48
von birkenfeld
7 Klassen und 2000 Zeilen? Hört sich nach viel an... vielleicht macht ihr euch das Leben auch schwerer, weil ihr versucht in Python wie in einer gewissen "modernen Hochsprache" zu programmieren, die ich jetzt mal ungenannt lassen will ;)

Verfasst: Montag 22. Juni 2009, 22:53
von cui
birkenfeld hat geschrieben:7 Klassen und 2000 Zeilen? Hört sich nach viel an... vielleicht macht ihr euch das Leben auch schwerer, weil ihr versucht in Python wie in einer gewissen "modernen Hochsprache" zu programmieren, die ich jetzt mal ungenannt lassen will ;)
Bitte fang jetzt nicht an über Programmiersprachen zu diskutieren!
Ich habe bisher vorallem Ruby und Java, aber auch Python, C# und Haskell programmiert.
Python war Vorgabe, weil es alle konnten.

PS: mit "modern" war "modern im Vergleich zu C" gemeint, nicht "modern im Vergleich zum Rückständigen Python". Versteh mich nicht falsch, ich mag Python eigentlich, ich habe damit programmieren gelernt und find es immer noch eine sehr schöne Sprache!

Verfasst: Montag 22. Juni 2009, 23:06
von cofi
Die Alternative ist eben eine dritte Datei zu verwenden.

Aber das löst ja das eigentlich Problem nicht, denn das ist das schlechte Design und das ist durchaus teurer was Wartbarkeit und Erweiterbarkeit angeht als die Probleme zu lösen.

Für CSV braucht es keinen besonderen Parser, das bringt Python schon mit. Das Verarbeiten ist aber euer Bier, vielleicht gibt es auch eine gut maschinenlesbare Version, die man einfach automatisch abernten kann.

Was birkenfeld meint ist, dass ihr nicht in Python sondern in der Programmiersprache mit dem `J` schreibt, die dazu neigt alles komplizierter zu machen als es zu sein braucht ;)

Verfasst: Montag 22. Juni 2009, 23:09
von Leonidas
cui hat geschrieben:Bitte fang jetzt nicht an über Programmiersprachen zu diskutieren!
Ich habe bisher vorallem Ruby und Java, aber auch Python, C# und Haskell programmiert.
Python war Vorgabe, weil es alle konnten.
Ich denke birkenfeld wollte eher darauf hinweisen dass 7 Klassen die 2000 Zeilen haben und in einem Modul stehen weil sie sich selbst gegenseitig referenzieren nach einem "Code Smell" klingen. Und 1 Datei pro Klasse macht die Sache eigentlich auch nicht übersichtlicher. Gute Trennung macht Dinge übersichtlicher, aber sowas kann man natürlich auf Syntaxebene nicht erzwingen.

Verfasst: Montag 22. Juni 2009, 23:14
von birkenfeld
cui hat geschrieben:
birkenfeld hat geschrieben:7 Klassen und 2000 Zeilen? Hört sich nach viel an... vielleicht macht ihr euch das Leben auch schwerer, weil ihr versucht in Python wie in einer gewissen "modernen Hochsprache" zu programmieren, die ich jetzt mal ungenannt lassen will ;)
Bitte fang jetzt nicht an über Programmiersprachen zu diskutieren!
Uh, das ist hier immer noch ein Forum... Aber ich wollte sowieso nicht auf eine Sprachendiskussion hinaus.
PS: mit "modern" war "modern im Vergleich zu C" gemeint, nicht "modern im Vergleich zum Rückständigen Python". Versteh mich nicht falsch, ich mag Python eigentlich, ich habe damit programmieren gelernt und find es immer noch eine sehr schöne Sprache!
Das bezweifle ich ja gar nicht :)

Um noch ein bisschen "produktiveres" beizutragen: zum einen würde es mich nicht mal sonderlich stören, wenn das eine Modul 2000 Zeilen hat, wenn diese *wirklich* eine Einheit bilden, die auseinanderzunehmen noch verwirrender wäre. Allerdings ist es auch möglich, dass sich eine natürliche Aufteilung ergibt, die sich euch einfach noch nicht angeboten hat.

Dann gibts immer noch die Möglichkeit, Imports lokal in Funktionen zu packen, womit man eigentlich wirklich notwendige zirkuläre Abhängigkeiten erschlägt:

Code: Alles auswählen

# eins.py
class A:
     def __init__(self):
          from zwei import C
          self.whatever = C()
class B:
    pass
# zwei.py
from eins import B
class C(B):
    pass
Trotzdem gibt es normalerweise eine Möglichkeit, gemeinsame "Vorfahren" (hier B) in ein weiteres Modul auszulagern, und so zirkuläre Module zu vermeiden.

Verfasst: Montag 22. Juni 2009, 23:20
von cui
cofi hat geschrieben:Was birkenfeld meint ist, dass ihr nicht in Python sondern in der Programmiersprache mit dem `J` schreibt, die dazu neigt alles komplizierter zu machen als es zu sein braucht ;)
Ich stimme euch da doch zu.
Denn was ich meinte ist, das mit das wohl bewusst ist, dass ich aber auch Sprachen gut kenne, in denen Dinge anders laufen.. ;)

Aber ich merke, letzlich war es ja wohl ich, der eine solche Diskussion losgetreten hat, darum möchte ich jetzt eigentlich nur noch allen für die schnellen Antworten danken, die ihr mir gegeben habt.

lg,
cui.

EDIT: @birkenfeld: Danke vorallem für deine Antwort grade eben. Das mit den lokalen Imports war mir neu. Und das mit dem Auslagern dieser Klasse ist mir im Laufe der Diskussion auch gekommen solangsam.. ich glaube dann müsste es funktionieren ohne zirkuläre Abhängigkeiten und ohne groß das Konzept zu ändern ;)

Verfasst: Montag 22. Juni 2009, 23:43
von BlackJack
@cui: Wie (un)übersichtlich so etwas wird, ist auch immer eine Frage der Werkzeuge. Ob die Klassen bei Java in Einzeldateien oder alle in Einer stehen, wäre mir zum Beispiel völlig egal, weil die typische Java-IDE Baumansichten von den Klassen bereitstellt, wo ich nur auf die Klasse oder Methode klicken muss und dann im Quelltext dort hin springe. Es gibt Python-IDEs die das auch bieten. Aber selbst ein einfacher Editor mit "code folding" schafft es sieben Klassen in einem Editorfenster gleichzeitig sichtbar zu machen.

Wenn Du die Tabellen schon als Code eingetippt hast, sollte es doch wohl möglich sein, die in eine Datendatei auszulagern, ohne dass Du sie noch einmal eintippen musst. Entweder durch entsprechendes umarbeiten des Quelltextes oder in dem Du Code schreibst, der die Daten aus dem Programm in eine Datendatei schreibt. Zum schreiben und lesen von CSV-Dateien gibt es in der Standardbibliothek das `csv`-Modul.