Nachdem ich bereits flache Pakete verwendet hatte, hatte ich nicht mit dem Problem gerechnet, auf das ich bei verschachtelten Paketen gestoßen bin. Hier ist…
Verzeichnislayout
dir
|
+-- test.py
|
+-- package
|
+-- __init__.py
|
+-- subpackage
|
+-- __init__.py
|
+-- module.py
Inhalt von drin.py
Beide package/__init__.py
und package/subpackage/__init__.py
sind leer.
Inhalt von module.py
# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...
Inhalt von test.py
(3 Versionen)
Version 1
# file test.py
from package.subpackage.module import *
print attribute1 # OK
Das ist die schlechte und unsichere Art, Dinge zu importieren (alles auf einmal zu importieren), aber es funktioniert.
Version 2
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1
Eine sicherere Methode zum Importieren, Element für Element, aber es schlägt fehl, Python will das nicht: schlägt mit der Meldung fehl: “No module named module”. Jedoch …
# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here
… sagt <module 'package.subpackage.module' from '...'>
. Das ist also ein Modul, aber das ist kein Modul /-P 😯 … äh
Fassung 3
# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK
Dieser funktioniert. Sie sind also entweder gezwungen, die ganze Zeit das Overkill-Präfix zu verwenden, oder verwenden den unsicheren Weg wie in Version #1 und werden von Python nicht zugelassen, um den sicheren handlichen Weg zu verwenden? Der bessere Weg, der sicher ist und unnötig lange Präfixe vermeidet, ist der einzige, den Python ablehnt? Ist das, weil es liebt import *
oder weil es überlange Präfixe liebt (was nicht hilft, diese Praxis durchzusetzen)?.
Entschuldigen Sie die harten Worte, aber das sind zwei Tage, an denen ich versucht habe, dieses dumme Verhalten zu umgehen. Wenn ich mich nicht irgendwo total geirrt habe, wird mir das das Gefühl geben, dass etwas in Pythons Modell von Paketen und Unterpaketen wirklich kaputt ist.
Anmerkungen
- Ich möchte mich nicht darauf verlassen
sys.path
um globale Nebenwirkungen zu vermeiden, noch auf*.pth
Dateien, die nur eine andere Möglichkeit sind, damit zu spielensys.path
mit den gleichen globalen Auswirkungen. Damit die Lösung sauber ist, muss sie nur lokal sein. Entweder kann Python Unterpakete verarbeiten, oder nicht, aber es sollte nicht erforderlich sein, mit der globalen Konfiguration zu spielen, um lokale Dinge verarbeiten zu können. - Ich habe auch versucht, Importe in zu verwenden
package/subpackage/__init__.py
aber es hat nichts gelöst, es tut dasselbe und beschwert sichsubpackage
ist kein bekanntes Modul, währendprint subpackage
sagt, es ist ein Modul (wieder seltsames Verhalten).
Vielleicht bin ich völlig falsch (die Option, die ich bevorzugen würde), aber das macht mich sehr enttäuscht über Python.
Irgendein anderer bekannter Weg außer den drei, die ich versucht habe? Etwas, von dem ich nichts weiß?
(Seufzen)
—– %< ----- bearbeiten ----- >% —–
Fazit bisher (nach den Kommentaren der Leute)
Es gibt nichts Besseres als ein echtes Unterpaket in Python, da alle Paketreferenzen nur in ein globales Wörterbuch gehen, was bedeutet, dass es kein lokales Wörterbuch gibt, was impliziert, dass es keine Möglichkeit gibt, lokale Paketreferenzen zu verwalten.
Sie müssen entweder das vollständige Präfix oder das kurze Präfix oder den Alias verwenden. Wie in:
Vollständige Präfixversion
from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)
Kurze Präfixversion (aber wiederholtes Präfix)
from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place
Oder eine Variation des oben Gesagten.
from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context
Faktorisierte Version
Wenn es Ihnen nichts ausmacht, mehrere Entitäten auf einmal in einem Batch zu importieren, können Sie:
from package.subpackage.module import attribute1, attribute2
# and etc.
Nicht in meinem ersten Lieblingsgeschmack (ich bevorzuge eine Importanweisung pro importierter Entität), aber vielleicht diejenige, die ich persönlich bevorzuge.
Aktualisierung (14.09.2012):
Scheint schließlich in der Praxis OK zu sein, außer mit einem Kommentar zum Layout. Anstelle des oben genannten habe ich verwendet:
from package.subpackage.module import (
attribute1,
attribute2,
attribute3,
...) # and etc.
Wie läuft es, wenn Sie “from . import module” in “/package/subpackage/__init__.py” schreiben?
– Markus Unterwaditzer
1. September 12 um 16:56 Uhr
Ihre “faktorisierte Version” scheint genau das Richtige für das zu sein, was Sie tun möchten. Wenn Sie eine separate Importzeile für Attribut1 und Attribut2 erstellen (wie Sie es “bevorzugen”), geben Sie sich nur absichtlich mehr Arbeit. Es gibt keinen Grund, das zu tun.
– BrenBarn
1. September 12 um 18:25 Uhr
Tut mir leid, aber ich verstehe nicht, was du willst. Könntest du deine Frage nochmal deutlicher formulieren? Was möchtest du genau machen? Ich meine, was würden Sie gerne schreiben, das nicht funktioniert, und wie würden Sie erwarten, dass es funktioniert? Nach dem, was ich gelesen habe, denke ich, dass Sie die Semantik des Imports wie Java oder vielleicht C umfassen. Zu guter Letzt: Sie können ein Modul “Stern-Import” sicher hinzufügen
__all__
Variable, die eine Liste der Namen enthält, die beim Star-Import exportiert werden sollen. Bearbeiten: Okay, beim Lesen der Antwort von BrenBarn habe ich verstanden, was Sie meinten.– Bakuriu
1. September 12 um 18:41 Uhr