Partieller Import möglich?

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.
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Erst mal meine Dateistruktur:

skript.py
PackageA
----> __init__.py
----> a.py
----> b.py
----> PackageB
--------> __init__.py
--------> c.py
--------> d.py

Im Skript wird "PackageA" importiert. In der "__init__" von "PackageA" importiere ich wiederum alles per * was in "a", "b" und "PackageB" enthalten ist. Das selbe macht auch die "__init__" von "PackageB", nur diesmal eben bei "c" und "d". Der Grund dafür ist, ich möchte schlicht über "PackageA.xyz" von überall aus auf alles Zugriff haben. Möchte also vermeiden im Modul "a", "PackageB" importieren zu müssen weil ich etwas aus dem Modul "c" brauche. Ich hoffe das ist soweit verständlich.

Nun zum Problem: Angenommen im Modul "a" gibt es einen SyntaxError oder einen ImportError, so habe ich keine Möglichkeit mehr auf Funktionen aus dem Modul "d" zuzugreifen. (Über: "from PackageA.PackageB.d import blub") Genau das hätte ich aber gerne, was mich letztendlich dazu bringt, anzunehmen dass meine "Import-Technik" nicht die richtige ist, falsch ist.

Wie aber mache ich das besser damit ich dieses Problem nicht mehr habe, aber trotzdem noch den gewünschten Effekt ("PackageA.xyz") erziele? (Es handelt sich um Python2.7, falls wichtig.)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Verstehe ich das richtig, dass du eine physische Pakethierarchie aufbaust, nur um sie dann logisch wieder kaputt zu machen?

Das konkrete Problem ist natuerlich eine Sache, die sich mit Fehlerbehandlung, sprich Exceptions, behandeln laesst. Also nur die `ImportError`, `SyntaxError` sollte man nun wirklich nicht mit Fehlerbehandlung umgehen ;)
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

cofi hat geschrieben:Verstehe ich das richtig, dass du eine physische Pakethierarchie aufbaust, nur um sie dann logisch wieder kaputt zu machen?
Ja. :lol: Ich finde das System von wxpython eben ganz praktisch, besonders was diverse Konstanten angeht (da gibts kein "from wx.constants import ID_YES"), möchte aber trotzdem nicht alles in ein einziges Modul packen.
cofi hat geschrieben:Das konkrete Problem ist natuerlich eine Sache, die sich mit Fehlerbehandlung, sprich Exceptions, behandeln laesst. Also nur die `ImportError`, `SyntaxError` sollte man nun wirklich nicht mit Fehlerbehandlung umgehen ;)
Umgehen? Damit stell ich doch nur kontrolliert fest dass es nicht funktioniert, habe dadurch aber immer noch keine Alternative.
deets

Ich verstehe dein Problem nicht. Wo kommen denn die kaputten Untermodule her? Was passiert denn, wenn ein Modul kaputt ist, aber dein Code einfach weiterlaeuft - wie stellst du denn sicher, dass du keine Folgefehler hast, weil auf Namen zugegriffen wird, die nicht bekannt sind?

Das alles klingt aeusserst suspekt. VisuaBasic hatte auch ein On Error Gosub Next - und das ist eine der daemlichsten Erfindungen der Programmiergeschichte (vor allem in den Haenden meines alten Chefs... ;))
lunar

@Gremlin: Du kannst apipkg nutzen, ob die Untermodule in einem Namensraum zu sammeln. "apipkg" importiert die Untermodule allerdings erst, wenn tatsächlich auf den Namen zugegriffen wird, so dass eine möglicher Fehler nicht bereits beim Import des obersten Moduls auftritt, sondern erst beim Zugriff auf einen Namen, der in einem unteren Modul definiert ist.

Unabhängig davon schließe ich mich der Meinung meiner Vorredner an. Zwar habe ich im Gegensatz zu cofi nichts dagegen, einen Namensraum auf mehrere Pakete/Module zu verteilen, und die "wichtigen" Namen, also jene, die Bestandteil der öffentlichen Schnittstelle sein sollen, in obersten Paket zu sammeln. Ich selbst mache das manchmal so. Das sollte sich aber in Grenzen halten. wx ist nicht unbedingt ein gutes Vorbild für API-Design, die Idee, tausende Namen in einen Namensraum zu packen, ist nicht unbedingt die beste.

Allerdings sehe ich kein Problem mit den von Dir beschriebenen Ausnahmen. Ein SyntaxError ist ein Fehler, der zur Laufzeit niemals auftreten sollte, und insofern auch nicht abgefangen werden muss. Einen ImportError dagegen kannst Du doch einfach abfangen?!
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

@deets
"Kaputt" ist bei mir gar nichts. Weiterlaufen tut mein Code auch nirgends, jedenfalls nicht bei Dingen die ich nicht "erwarte". Es sei denn du empfindest es als suspekt wenn ich sys.excepthook benutze um einen Dialog zur Fehlerberichterstattung anzuzeigen. :P (Und nachdem der Benutzer sich entschieden hat, das Programm sauber beende, sofern der Debug-Modus nicht läuft.) Mehr gibts unten zu lesen :mrgreen:

@lunar
Danke, apipkg werd ich mir mal ansehen. Die Sache ist die, dass ich das Programm mit py2exe verteile. py2exe verfügt bereits über eine Art Log-Funktionalität, die mir aber nicht ausreicht. Ich möchte deshalb meine Fehlerberichterstattung nutzen. Dazu wollte ich auf meine bereits vorhandenen Daten zugreifen um statt des Dialogs von py2exe ("Errors occured. See logfile...") meinen eigenen anzeigen. Da kann dann natürlich auch "irgendwas" schief gehen, aber zumindest kann man mir dann nicht nachsagen ich hätte nicht alles versucht. :roll:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

lunar hat geschrieben:Zwar habe ich im Gegensatz zu cofi nichts dagegen, einen Namensraum auf mehrere Pakete/Module zu verteilen, und die "wichtigen" Namen, also jene, die Bestandteil der öffentlichen Schnittstelle sein sollen, in obersten Paket zu sammeln. Ich selbst mache das manchmal so. Das sollte sich aber in Grenzen halten.
Na da liest du jetzt aber zuviel in die Nachfrage hinein ;) Aber gerade durch die *-Importe habe ich nicht das Gefuehl, dass das der Weg zu einem schoenen und gut benutzbaren API ist. Aber letztlich ist das natuerlich vom Einzelfall abgaengig.
deets

Ich bin vielleicht heute etwas auf der begriffstutzigen Seite des Lebens - aber ich verstehe das Problem immer noch nicht.

Das du erweiterte Fehlerbehandlung einfuehren willst ist ja gut so. Aber das hat doch nix mit importen zu tun! Es hoert sich so an, als ob du Seiteneffekte bereits beim importieren hast, die dann zu Fehlerzustaenden fuehren. Wenn das der Grund ist, dann solltest du statt lazy importing und maskierung von ImportError lieber auf diese Seiteneffekte verzichten, und stattdessen eine sauberes Bootstrapping deiner Anwendung vornehmen.

Also, was genau *kann* denn schiefgehen beim Import?
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Naja, ich nehm mal die erste Veröffentlichung meines Programms als Beispiel: Ich entwickle auf Windows 7 64bit, habe selbst kein Windows XP 32bit zur Hand und jeder den ich sonst noch so kenne auch nicht. Als also der erste mit XP als System das Programm starten wollte, verweigerte es den Start. Warum? Weil py2exe eine dll von Windows 7 mit in die Abhängigkeiten gepackt hatte mit der wiederum XP nichts anzufangen wusste. Von diesem Fehler hab ich aber erst erfahren, als die 32bit Version des Programms schon ein paar mal runtergeladen wurde. Hätte ich es vorher gewusst, hätte ich den Download früher verhindern können. Naja...

Und weils so schön ist: Wenn ich ein Update rausbringe, läuft das bei mir automatisch ab. (Kompilieren, Installer erstellen und Upload) Falls ich nun irgendwo ein neues Modul importiere, py2exe nun eine neue Abhängigkeit registriert und ich vergessen habe das Installer-Skript dahingehend zu aktualisieren, landet diese neue .dll oder .pyd nicht im Installer. (Natürlich mach ich vorher grobe Tests, aber man weiß ja nie, ne?)
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dein Problem mit py2exe liegt halt in der Natur der Sache bei vorkompilierten Programmen. Natürlich muss dies immer für die Plattform gemacht werden, auf der es eingesetzt werden soll. Das Problem bestünde natürlich nicht, wenn sich deine User selber Python herunterladen würden, um dann den Quellcode auszuführen. Du kannst ja eine Anleitung schreiben oder ein Installationsskript.
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Blöd nur, dass ich mir bereits "Simplicity matters" auf die Kappe geschrieben habe. :P Außerdem funktionierts ja jetzt. Und falls es doch mal wieder nicht funktioniert und ich tatsächlich auf einem 32bit System kompilieren muss, nehm ich halt endlich mal die kostenlose XP Version in Anspruch die bei Windows 7 "dabei" war :lol:
deets

Ah, ok, also Plattformprobleme.

Trotzdem finde ich deine Loesungsskizze unpassend. "Partielle Importe" helfen dir denke ich nicht. Stattdessen wuerde ich eine Art Mantel-Skript machen, bzw dein skript.py so gestalten, dass es bei ImportError eben die Fehlermeldung in der dir genehmen Art und Weise darstellt. Natuerlich setzt das vorraus, dass alles, was du dazu brauchst auch vorhanden ist, unter allen Umstaenden.
deets

snafu hat geschrieben:Dein Problem mit py2exe liegt halt in der Natur der Sache bei vorkompilierten Programmen. Natürlich muss dies immer für die Plattform gemacht werden, auf der es eingesetzt werden soll. Das Problem bestünde natürlich nicht, wenn sich deine User selber Python herunterladen würden, um dann den Quellcode auszuführen. Du kannst ja eine Anleitung schreiben oder ein Installationsskript.
Joa, und darum ist Linux auch so ein bahnbrechender Erfolg auf dem Desktop beschert.

Es gibt Endanwender, die sich - sehr zu Recht - mit solchen Dingen nicht beschaeftigen sollen. Mein Vater (auf Ubuntu 10.04) hat mich neulich gefragt, wie er denn den neuen FireFox 4 bekommt. Tjoa. Er surft erstmal mit 3 weiter. Denn so leicht es fuer mich selbst ist, mal kurz nen PPA einzurichten, dem alten Herren ist das nicht zuzumuten.

Oh, nur am Rande: ich nutze Linux seit Suse... irgendwas, Kernel 1.2 ;)
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

deets hat geschrieben:Stattdessen wuerde ich eine Art Mantel-Skript machen, bzw dein skript.py so gestalten, dass es bei ImportError eben die Fehlermeldung in der dir genehmen Art und Weise darstellt.
Naja, ein Mantel-Skript hab ich in zweierlei Hinsicht. Zum einen meine "skript.py" zum anderen py2exe. Das mit py2exe kompilierte Programm verweigert ja nicht einfach mit der typischen Windows Fehlermeldung den Dienst, sondern schreibt das Traceback in ein logfile. (Natürlich geht das nur wenn etwas meinem Programmcode fehlt und nicht wenn bereits die exe meckert.)

Insofern helfen mir also schon partielle Importe, wenn meine Vorstellungskraft nicht gerade total versagt. :roll:
deets

Aber wie genau denn? Wenn du nicht alles importiert bekommst, aber das nicht mitbekommst, dann schmiert dein Programm *irgendwie* ab - spaeter halt.

Was ist denn das Problem, den ImportError hoch oben zu fangen + zu reporten? Oder andersherum, was bringt dir der partielle import genau?
Gremlin
User
Beiträge: 166
Registriert: Freitag 28. Mai 2010, 23:49

Naja, in der "skript.py" wird "import PackageA" ausgeführt. Im Moment noch ohne try...except und dann wir die Application-Class von jenem Packet instanziert und der MainLoop gestartet. (Grob dargestellt) Indem ich aber "PackageA" importiere, importiere ich *alles* aus allen anderen Subpackages und -modulen ebenfalls. Wenn also eines dieser Pakete/Module etwas importiert was nicht vorhanden ist -> Ende.

Und genau in diesem Fall, möchte ich aber den Dialog den ich für die Fehlerberichterstattung benutze trotzdem importieren und benutzen können. Aber ohne partiellen Import tritt der selbe ImportError dann wieder auf. ;) Klar, ich kann den Dialog auslagern, aber das will ich ja gerade verhindern.
BlackJack

@Gremlin: Genau das wäre aber wohl die saubere Lösung.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

deets hat geschrieben:
snafu hat geschrieben:Dein Problem mit py2exe liegt halt in der Natur der Sache bei vorkompilierten Programmen. Natürlich muss dies immer für die Plattform gemacht werden, auf der es eingesetzt werden soll. Das Problem bestünde natürlich nicht, wenn sich deine User selber Python herunterladen würden, um dann den Quellcode auszuführen. Du kannst ja eine Anleitung schreiben oder ein Installationsskript.
Joa, und darum ist Linux auch so ein bahnbrechender Erfolg auf dem Desktop beschert.

Es gibt Endanwender, die sich - sehr zu Recht - mit solchen Dingen nicht beschaeftigen sollen. Mein Vater (auf Ubuntu 10.04) hat mich neulich gefragt, wie er denn den neuen FireFox 4 bekommt. Tjoa. Er surft erstmal mit 3 weiter. Denn so leicht es fuer mich selbst ist, mal kurz nen PPA einzurichten, dem alten Herren ist das nicht zuzumuten.
Ich weiß nicht, wie du jetzt auf Linux kommst. Die Dinger aus dem PPA haben letztlich das selbe Problem: Wenn man nicht gerade für verschiedenste Architekturen und für etliche Derivate Pakete gebaut hat, dann muss der Endanwender auch sehen, dass er möglichst ein vielbenutztes System verwendet (prominentes Beispiel wäre wohl Ubuntu), wenn er das Paket verwenden will. Im Übrigen fehlt für den Schritt, dass jeder Anfänger ein PPA installieren kann, ja eigentlich nur etwas analoges zu `apturl` - also ein Browser-Plugin für eine 1-Klick-Installation. Und versteh mich bitte nicht falsch: Ich bin ebenfalls kein Freund von Selberkompilieren und froh, dass mir das allermeiste fertig vor die Nase gesetzt wird. Trotzdem bleibt es ja wohl Fakt, dass Automatisierungsprozesse in dieser Hinsicht plattformbedingte Einschränkungen mit sich bringen. Wenn es für Windows irgendein cooles Installationsskript-Framework gäbe, dass auf dem Rechner nach einer Python-Installation suchen, bei Abhängigkeiten ggf `easy_install` bzw `pip` zur Verwendung installieren kann usw, dann bräuchte man sowieso keine "Python-Compiler" mehr.
deets

so wie sich das anhoert dann also doch Seiteneffekte. Mir will nicht so recht klarwerden, warum es ein Problem sein soll, grob gesagt sowas zu machen:

Code: Alles auswählen

# skript.py

import sichere_sache

try:
    import PackageA
except ImportErro:
    sichere_sache.toller_report()


Es gibt unter Umstaenden schon Moeglichkeiten, mit den in PEP302 dargestellten Import-Hooks weiterzukommen. Aber ich halte das fuer verschwurbelt und letztlich nicht wirklich robuster.
deets

snafu hat geschrieben: Ich weiß nicht, wie du jetzt auf Linux kommst.
Ganz einfach - weil es ja die Linux-Attituede ist, jemandem das RTFM eines INSTALL-Files an den Kopp zu hauen ;) Natuerlich kann man genauso auf anderen Plattformen vorgehen, aber unter Linux ist es halt verbreitet, und ist IMHO mitverantwortlich fuer den eher maessigen Desktoperfolg.
snafu hat geschrieben: Die Dinger aus dem PPA haben letztlich das selbe Problem: Wenn man nicht gerade für verschiedenste Architekturen und für etliche Derivate Pakete gebaut hat, dann muss der Endanwender auch sehen, dass er möglichst ein vielbenutztes System verwendet (prominentes Beispiel wäre wohl Ubuntu), wenn er das Paket verwenden will. Im Übrigen fehlt für den Schritt, dass jeder Anfänger ein PPA installieren kann, ja eigentlich nur etwas analoges zu `apturl` - also ein Browser-Plugin für eine 1-Klick-Installation. Und versteh mich bitte nicht falsch: Ich bin ebenfalls kein Freund von Selberkompilieren und froh, dass mir das allermeiste fertig vor die Nase gesetzt wird. Trotzdem bleibt es ja wohl Fakt, dass Automatisierungsprozesse in dieser Hinsicht plattformbedingte Einschränkungen mit sich bringen. Wenn es für Windows irgendein cooles Installationsskript-Framework gäbe, dass auf dem Rechner nach einer Python-Installation suchen, bei Abhängigkeiten ggf `easy_install` bzw `pip` zur Verwendung installieren kann usw, dann bräuchte man sowieso keine "Python-Compiler" mehr.
Das ist alles richtig und schoen - mir ging's aber um den konkreten Fall, das der gute Gremlin nunmal Endanwender-Software bereitstellen mag, du ihm aber vorschlugst, das ganze doch zum selbst-basteln anzubieten. Das loest aber nicht sein Problem, sondern verlagert es auf die Endanwender-Schultern, die das ueblicherweise nicht verkraften.

Das ganze Thema Package-Managment usw. ist sowieso ziemlich heftig - auch und gerade dann noch mit der Interaktion Python/PyPI.

Auf der Europython 2009 habe ich den Talk eines Amis gesehen, der versucht hat, mit MS zusammen build-bots zu bauen, damit Entwickler eben genau die Chance haben, fuer die verschiedenen Plattformen zu entwickeln. Hab davon nie wieder was gehoert :(
Antworten