Hinweis: Obwohl JavaScript für diese Website nicht unbedingt erforderlich ist, werden Ihre Interaktionsmöglichkeiten mit den Inhalten eingeschränkt sein. Bitte aktivieren Sie JavaScript für das volle Erlebnis.

Eingebauter Paket-Support in Python 1.5

Eingebauter Paket-Support in Python 1.5

Ab Python Version 1.5a4 ist Paket-Support in den Python-Interpreter integriert. Dies implementiert eine leicht vereinfachte und modifizierte Version der Paket-Import-Semantik, die vom Modul "ni" eingeführt wurde.

"Paket-Import" ist eine Methode, um den Modul-Namensraum von Python mithilfe von "punktierten Modulnamen" zu strukturieren. Zum Beispiel bezeichnet der Modulname A.B ein Untermodul namens B in einem Paket namens A. So wie die Verwendung von Modulen die Autoren verschiedener Module davor bewahrt, sich um die globalen Variablennamen der anderen sorgen zu müssen, spart die Verwendung von punktierten Modulnamen die Autoren von Multi-Modul-Paketen wie NumPy oder PIL davor, sich um die Modulnamen der anderen sorgen zu müssen.

Ab Python Version 1.3 wurde der Paket-Import durch ein Standard-Python-Bibliotheksmodul namens "ni" unterstützt. (Der Name soll ein Akronym für New Import sein, bezieht sich aber eigentlich auf die Knights Who Say Ni aus dem Film Monty Python and the Holy Grail, die, nachdem die Ritter von König Arthur einen Strauch zurückgebracht haben, ihre Namen in die Knights Who Say Neeeow ... Wum ... Ping geändert haben - aber das ist eine andere Geschichte.)

Das ni-Modul bestand ausschließlich aus Benutzer-Code, abgesehen von einigen Modifikationen des Python-Parsers (ebenfalls in 1.3 eingeführt), um Importanweisungen wie "import A.B.C" und "from A.B.C import X" zu akzeptieren. Wenn ni nicht aktiviert war, führte die Verwendung dieser Syntax zu einem Laufzeitfehler "No such module". Sobald ni aktiviert war (durch Ausführung von "import ni" vor dem Import anderer Module), suchte der Import-Hook von ni nach dem Untermodul des richtigen Pakets.

Der neue Paket-Support ist so konzipiert, dass er ni ähnelt, wurde jedoch optimiert und einige Funktionen wurden geändert oder entfernt.

Ein Beispiel

Angenommen, Sie möchten ein Paket für die einheitliche Verarbeitung von Sounddateien und Sounddaten entwerfen. Es gibt viele verschiedene Sounddateiformate (die normalerweise durch ihre Erweiterung erkannt werden, z. B. .wav, .aiff, .au), sodass Sie möglicherweise eine wachsende Sammlung von Modulen zur Konvertierung zwischen den verschiedenen Dateiformaten erstellen und pflegen müssen. Es gibt auch viele verschiedene Operationen, die Sie auf Sounddaten ausführen möchten (z. B. Mischen, Hinzufügen von Echo, Anwenden einer Equalizer-Funktion, Erstellen eines künstlichen Stereo-Effekts), sodass Sie zusätzlich einen endlosen Strom von Modulen schreiben werden, um diese Operationen durchzuführen. Hier ist eine mögliche Struktur für Ihr Paket (ausgedrückt in Form eines hierarchischen Dateisystems)

Sound/				Top-level package
      __init__.py		Initialize the sound package
      Utils/			Subpackage for internal use
            __init__.py
            iobuffer.py
	    errors.py
	    ...
      Formats/			Subpackage for file format conversions
              __init__.py
              wavread.py
	      wavwrite.py
	      aiffread.py
	      aiffwrite.py
	      auread.py
	      auwrite.py
	      ...
      Effects/			Subpackage for sound effects
              __init__.py
	      echo.py
	      surround.py
	      reverse.py
	      ...
      Filters/			Subpackage for filters
              __init__.py
              equalizer.py
	      vocoder.py
	      karaoke.py
	      dolby.py
	      ...

Benutzer des Pakets können einzelne Module aus dem Paket importieren, zum Beispiel

import Sound.Effects.echo
Dies lädt das Untermodul Sound.Effects.echo. Es muss mit seinem vollständigen Namen referenziert werden, z. B. Sound.Effects.echo.echofilter(input, output, delay=0.7, atten=4)

from Sound.Effects import echo
Dies lädt ebenfalls das Untermodul echo und macht es ohne seinen Paket-Präfix verfügbar, sodass es wie folgt verwendet werden kann: echo.echofilter(input, output, delay=0.7, atten=4)

from Sound.Effects.echo import echofilter
Auch dies lädt das Untermodul echo, macht aber seine Funktion echofilter direkt verfügbar: echofilter(input, output, delay=0.7, atten=4)

Beachten Sie, dass beim Verwenden von from package import item das Item entweder ein Untermodul (oder Unterpaket) des Pakets sein kann oder ein anderer Name, der im Paket definiert ist, wie eine Funktion, Klasse oder Variable. Die Importanweisung prüft zuerst, ob das Item im Paket definiert ist. Wenn nicht, wird angenommen, dass es sich um ein Modul handelt, und es wird versucht, es zu laden. Wenn es nicht gefunden werden kann, wird ImportError ausgelöst.

Umgekehrt muss bei der Verwendung von Syntax wie import item.subitem.subsubitem jedes Item außer dem letzten ein Paket sein; das letzte Item kann ein Modul oder ein Paket sein, aber keine Klasse oder Funktion oder Variable, die im vorherigen Item definiert ist.

Importieren von * aus einem Paket; das Attribut __all__

Was passiert nun, wenn der Benutzer from Sound.Effects import * schreibt? Idealerweise hofft man, dass dies irgendwie das Dateisystem durchsucht, feststellt, welche Untermodule im Paket vorhanden sind, und sie alle importiert. Leider funktioniert dieser Vorgang auf Mac- und Windows-Plattformen nicht sehr gut, da das Dateisystem nicht immer genaue Informationen über die Groß-/Kleinschreibung eines Dateinamens hat! Auf diesen Plattformen gibt es keine garantierte Möglichkeit zu wissen, ob eine Datei ECHO.PY als Modul echo, Echo oder ECHO importiert werden soll. (Zum Beispiel hat Windows 95 die ärgerliche Angewohnheit, alle Dateinamen mit einem großgeschriebenen ersten Buchstaben anzuzeigen.) Die DOS 8+3-Dateinamensbeschränkung fügt ein weiteres interessantes Problem für lange Modulnamen hinzu.

Die einzige Lösung besteht darin, dass der Paketautor einen expliziten Index des Pakets bereitstellt. Die Importanweisung verwendet die folgende Konvention: Wenn der Code von __init__.py eines Pakets eine Liste namens __all__ definiert, wird diese als Liste der Modulnamen übernommen, die importiert werden sollen, wenn from package import * angetroffen wird. Es liegt am Paketautor, diese Liste bei der Veröffentlichung einer neuen Version des Pakets auf dem neuesten Stand zu halten. Paketautoren können sich auch entscheiden, dies nicht zu unterstützen, wenn sie keinen Nutzen darin sehen, * aus ihrem Paket zu importieren. Zum Beispiel könnte die Datei Sounds/Effects/__init__.py den folgenden Code enthalten

__all__ = ["echo", "surround", "reverse"]
Dies würde bedeuten, dass from Sound.Effects import * die drei genannten Untermodule des Sound-Pakets importieren würde.

Wenn __all__ nicht definiert ist, importiert die Anweisung from Sound.Effects import * nicht alle Untermodule aus dem Paket Sound.Effects in den aktuellen Namensraum; sie stellt lediglich sicher, dass das Paket Sound.Effects importiert wurde (möglicherweise mit Ausführung seines Initialisierungscodes, __init__.py) und importiert dann alle im Paket definierten Namen. Dies schließt alle Namen ein, die von __init__.py definiert wurden (und Untermodule, die explizit geladen wurden). Es schließt auch alle Untermodule des Pakets ein, die durch frühere Importanweisungen explizit geladen wurden, z. B.

import Sound.Effects.echo
import Sound.Effects.surround
from Sound.Effects import *
In diesem Beispiel werden die Module echo und surround in den aktuellen Namensraum importiert, da sie im Paket Sound.Effects definiert sind, wenn die from...import-Anweisung ausgeführt wird. (Dies funktioniert auch, wenn __all__ definiert ist.)

Beachten Sie, dass die Praxis, * aus einem Modul oder Paket zu importieren, im Allgemeinen missbilligt wird, da sie oft zu schlecht lesbarem Code führt. Es ist jedoch in Ordnung, sie zu verwenden, um in interaktiven Sitzungen Tipparbeit zu sparen, und bestimmte Module sind so konzipiert, dass sie nur Namen exportieren, die bestimmten Mustern folgen.

Denken Sie daran, dass es nichts Falsches daran gibt, from Package import specific_submodule zu verwenden! Tatsächlich wird dies zur empfohlenen Notation, es sei denn, das importierende Modul muss Untermodule mit demselben Namen aus verschiedenen Paketen verwenden.

Intra-Paket-Referenzen

Die Untermodule müssen sich oft gegenseitig referenzieren. Zum Beispiel könnte das surround-Modul das echo-Modul verwenden. Tatsächlich sind solche Referenzen so häufig, dass die Importanweisung zuerst im enthaltenden Paket sucht, bevor sie den Standard-Modul-Suchpfad durchsucht. Somit kann das surround-Modul einfach import echo oder from echo import echofilter verwenden. Wenn das importierte Modul nicht im aktuellen Paket gefunden wird (dem Paket, dessen aktuelles Modul ein Untermodul ist), sucht die Importanweisung nach einem Top-Level-Modul mit dem gegebenen Namen.

Wenn Pakete in Unterpakete strukturiert sind (wie im Fall des Sound-Pakets im Beispiel), gibt es keine Abkürzung, um auf Untermodule von Geschwisterpaketen zu verweisen – der vollständige Name des Unterpakets muss verwendet werden. Zum Beispiel, wenn das Modul Sound.Filters.vocoder das echo-Modul im Paket Sound.Effects verwenden muss, kann es from Sound.Effects import echo verwenden.

(Man könnte eine Notation entwerfen, um auf übergeordnete Pakete zu verweisen, ähnlich der Verwendung von ".." für das übergeordnete Verzeichnis in Unix- und Windows-Dateisystemen. Tatsächlich unterstützte ni dies mit __ für das Paket, das das aktuelle Modul enthält, __.__ für das übergeordnete Paket und so weiter. Dieses Feature wurde wegen seiner Unhandlichkeit gestrichen; da die meisten Pakete eine relativ flache Unterstruktur haben werden, ist dies kein großer Verlust.)

Details

Pakete sind auch Module!

Warnung: Das Folgende kann für diejenigen verwirrend sein, die mit der Java-Paketnotation vertraut sind, die der von Python ähnlich ist, aber anders.

Immer wenn ein Untermodul eines Pakets geladen wird, stellt Python sicher, dass das Paket selbst zuerst geladen wird, indem es gegebenenfalls seine __init__.py-Datei lädt. Das Gleiche gilt für Pakete. Somit stellt die Anweisung import Sound.Effects.echo zuerst sicher, dass Sound geladen ist; dann stellt sie sicher, dass Sound.Effects geladen ist; und erst dann stellt sie sicher, dass Sound.Effects.echo geladen ist (indem sie es lädt, falls es noch nicht geladen wurde).

Nach dem Laden ist der Unterschied zwischen einem Paket und einem Modul minimal. Tatsächlich werden beide durch Modulobjekte dargestellt und beide in der Tabelle der geladenen Module, sys.modules, gespeichert. Der Schlüssel in sys.modules ist der vollständige punktierte Name eines Moduls (der nicht immer derselbe Name ist wie in der Importanweisung). Dies ist auch der Inhalt der Variablen __name__ (die den vollständigen Namen des Moduls oder Pakets angibt).

Die Variable __path__

Die einzige Unterscheidung zwischen Paketen und Modulen liegt im Vorhandensein oder Fehlen der Variablen __path__. Diese ist nur für Pakete vorhanden. Sie wird mit einer Liste von einem Element initialisiert, die den Verzeichnisnamen des Pakets enthält (ein Unterverzeichnis eines Verzeichnisses auf sys.path). Das Ändern von __path__ ändert die Liste der Verzeichnisse, die nach Untermodulen des Pakets durchsucht werden. Zum Beispiel könnte das Paket Sound.Effects plattformspezifische Untermodule enthalten. Es könnte die folgende Verzeichnisstruktur verwenden

Sound/
      __init__.py
      Effects/			# Generic versions of effects modules
              __init__.py
              echo.py
	      surround.py
	      reverse.py
	      ...
              plat-ix86/	# Intel x86 specific effects modules
	                echo.py
			surround.py
	      plat-PPC/		# PPC specific effects modules
	                echo.py

Die Datei Effects/__init__.py könnte ihre __path__-Variable so manipulieren, dass das plattformspezifische Unterverzeichnis vor dem Haupt-Effects-Verzeichnis kommt, sodass die plattformspezifischen Implementierungen bestimmter Effekte (falls vorhanden) die generischen (wahrscheinlich langsameren) Implementierungen überschreiben. Zum Beispiel

platform = ...			# Figure out which platform applies
dirname = __path__[0]		# Package's main folder
__path__.insert(0, os.path.join(dirname, "plat-" + platform))

Wenn es nicht erwünscht ist, dass plattformspezifische Untermodule generische Module mit demselben Namen verdecken, sollte __path__.append(...) anstelle von __path__.insert(0, ...) verwendet werden.

Beachten Sie, dass die plat-* Unterverzeichnisse *keine* Unterpakete von Effects sind – die Datei Sound/Effects/plat-PPC/echo.py entspricht dem Modul Sound.Effects.echo.

Dummy-Einträge in sys.modules

Bei der Verwendung von Paketen finden Sie gelegentlich fehlerhafte Einträge in sys.modules, z. B. sys.modules['Sound.Effects.string'] könnte den Wert None haben. Dies ist ein "Indirektions"-Eintrag, der erstellt wurde, weil ein Untermodul im Paket Sound.Effects das Top-Level-Modul string importiert hat. Sein Zweck ist eine wichtige Optimierung: Da die Importanweisung nicht erkennen kann, ob ein lokales oder ein globales Modul gewünscht ist, und da die Regeln besagen, dass ein lokales Modul (im selben Paket) ein globales Modul mit demselben Namen verdeckt, muss die Importanweisung den Suchpfad des Pakets durchsuchen, bevor nach einem (möglicherweise bereits importierten) globalen Modul gesucht wird. Da das Durchsuchen des Paketpfads eine relativ teure Operation ist und das Importieren eines bereits importierten Moduls billig sein soll (in der Größenordnung von ein oder zwei Dictionary-Lookups), ist eine Optimierung angebracht. Der Dummy-Eintrag vermeidet die Suche auf dem Paketpfad, wenn dasselbe globale Modul zum zweiten Mal von einem Untermodul desselben Pakets importiert wird.

Dummy-Einträge werden nur für Module erstellt, die auf der Top-Level-Ebene gefunden werden; wenn das Modul überhaupt nicht gefunden wird, schlägt der Import fehl und die Optimierung ist im Allgemeinen nicht erforderlich. Darüber hinaus könnte der Benutzer im interaktiven Modus das Modul als paketlokales Untermodul erstellen und den Import wiederholen; wenn ein Dummy-Eintrag erstellt worden wäre, würde dieser nicht gefunden werden. Wenn der Benutzer die Paketstruktur ändert, indem er ein lokales Untermodul mit demselben Namen wie ein bereits im Paket verwendetes globales Modul erstellt, ist das Ergebnis im Allgemeinen als "Chaos" bekannt, und die richtige Lösung ist, den Interpreter zu beenden und von vorne zu beginnen.

Was, wenn ich ein Modul und ein Paket mit demselben Namen habe?

Sie haben möglicherweise ein Verzeichnis (auf sys.path), das sowohl ein Modul spam.py als auch ein Unterverzeichnis spam enthält, das eine __init__.py enthält (ohne die __init__.py wird ein Verzeichnis nicht als Paket erkannt). In diesem Fall hat das Unterverzeichnis Vorrang, und das Importieren von spam ignoriert die Datei spam.py und lädt stattdessen das Paket spam. Wenn das Modul spam.py Vorrang haben soll, muss es in einem Verzeichnis platziert werden, das früher in sys.path erscheint.

(Tipp: Die Suchreihenfolge wird durch die Liste der Suffixe bestimmt, die von der Funktion imp.get_suffixes() zurückgegeben werden. Normalerweise werden die Suffixe in folgender Reihenfolge durchsucht: ".so", "module.so", ".py", ".pyc". Verzeichnisse kommen in dieser Liste nicht explizit vor, stehen aber vor allen Einträgen darin.)

Ein Vorschlag zur Installation von Paketen

Damit ein Python-Programm ein Paket verwenden kann, muss das Paket für die Importanweisung auffindbar sein. Mit anderen Worten, das Paket muss ein Unterverzeichnis eines Verzeichnisses sein, das sich auf sys.path befindet.

Traditionell war der einfachste Weg, um sicherzustellen, dass ein Paket auf sys.path vorhanden ist, es entweder in der Standardbibliothek zu installieren oder Benutzer die sys.path durch Setzen ihrer $PYTHONPATH Shell-Umgebungsvariable erweitern zu lassen. In der Praxis führen beide Lösungen schnell zu Chaos.

Dedizierte Verzeichnisse

In Python 1.5 wurde eine Konvention etabliert, die Chaos verhindern soll, indem dem Systemadministrator mehr Kontrolle gegeben wird. Zunächst werden zwei zusätzliche Verzeichnisse am Ende des Standard-Suchpfads hinzugefügt (vier, wenn der Installationspräfix und der Ausführungspräfix unterschiedlich sind). Diese befinden sich relativ zum Installationspräfix (der standardmäßig /usr/local ist)

  • $prefix/lib/python1.5/site-packages
  • $prefix/lib/site-python

Das Verzeichnis site-packages kann für Pakete verwendet werden, die wahrscheinlich von der Python-Version abhängen (z. B. Pakete, die Shared Libraries enthalten oder neue Features verwenden). Das Verzeichnis site-python wird für die Abwärtskompatibilität mit Python 1.4 und für reine Python-Pakete oder Module verwendet, die nicht von der verwendeten Python-Version abhängig sind.

Die empfohlene Verwendung dieser Verzeichnisse ist, jedes Paket in einem eigenen Unterverzeichnis entweder im Verzeichnis site-packages oder site-python zu platzieren. Das Unterverzeichnis sollte der Paketname sein, der als Python-Bezeichner akzeptabel sein sollte. Dann kann jedes Python-Programm Module im Paket importieren, indem es deren vollständigen Namen angibt. Zum Beispiel könnte das im Beispiel verwendete Sound-Paket im Verzeichnis $prefix/lib/python1.5/site-packages/Sound installiert werden, um Importanweisungen wie import Sound.Effects.echo zu ermöglichen).

Hinzufügen einer Indirektionsstufe

Einige Standorte möchten ihre Pakete an anderen Stellen installieren, möchten aber dennoch, dass sie von allen Python-Programmen auf allen ihren Benutzern importierbar sind. Dies kann auf zwei verschiedene Arten erreicht werden

Symbolische Links
Wenn das Paket für den punktierten Import strukturiert ist, platzieren Sie einen symbolischen Link auf sein Top-Level-Verzeichnis im Verzeichnis site-packages oder site-python. Der Name des symbolischen Links sollte der Paketname sein; zum Beispiel könnte das Sound-Paket einen symbolischen Link $prefix/lib/python1.5/site-packages/Sound haben, der auf /usr/home/soundguru/lib/Sound-1.1/src zeigt.

Pfadkonfigurationsdateien
Wenn das Paket wirklich das Hinzufügen eines oder mehrerer Verzeichnisse zu sys.path erfordert (z. B. weil es noch nicht für den punktierten Import strukturiert ist), kann eine "Pfadkonfigurationsdatei" namens package.pth in entweder dem Verzeichnis site-python oder site-packages platziert werden. Jede Zeile in dieser Datei (außer Kommentaren und leeren Zeilen) wird als Verzeichnisname betrachtet, der zu sys.path hinzugefügt wird. Relative Pfadnamen sind zulässig und werden relativ zu dem Verzeichnis interpretiert, das die .pth-Datei enthält.

Die .pth-Dateien werden in alphabetischer Reihenfolge gelesen, wobei die Groß-/Kleinschreibung mit der des lokalen Dateisystems übereinstimmt. Das bedeutet, wenn Sie den unwiderstehlichen Drang verspüren, Spiele mit der Reihenfolge zu spielen, in der Verzeichnisse durchsucht werden, können Sie dies zumindest auf vorhersagbare Weise tun. (Dies ist keine Befürwortung. Eine typische Installation sollte keine oder nur sehr wenige .pth-Dateien haben, oder etwas ist falsch, und wenn Sie die Suchreihenfolge anpassen müssen, ist etwas *sehr* falsch. Nichtsdestotrotz entsteht manchmal die Notwendigkeit, und so können Sie es tun, wenn Sie müssen.)

Hinweise für Mac- und Windows-Plattformen

Auf Mac und Windows sind die Konventionen leicht unterschiedlich. Das übliche Verzeichnis für die Paketinstallation auf diesen Plattformen ist das Stammverzeichnis (oder ein Unterverzeichnis) des Python-Installationsverzeichnisses, das für die installierte Python-Version spezifisch ist. Dies ist auch das (einzige) Verzeichnis, das nach Pfadkonfigurationsdateien (*.pth) durchsucht wird.

Unterverzeichnisse des Standardbibliotheksverzeichnisses

Da jedes Unterverzeichnis eines Verzeichnisses auf sys.path nun implizit als Paket verwendbar ist, könnte man leicht verwirrt sein, ob diese als solche gedacht sind. Angenommen, es gibt ein Unterverzeichnis namens tkinter, das ein Modul Tkinter.py enthält. Sollte man import Tkinter oder import tkinter.Tkinter schreiben? Wenn das Unterverzeichnis tkinter auf dem Pfad liegt, funktionieren beide, aber das schafft unnötige Verwirrung.

Ich habe eine einfache Namenskonvention etabliert, die diese Verwirrung beseitigen soll: Nicht-Paket-Verzeichnisse müssen einen Bindestrich in ihrem Namen haben. Insbesondere wurden alle plattformspezifischen Unterverzeichnisse (sunos5, win, mac usw.) in einen Namen mit dem Präfix "plat-" umbenannt. Die Unterverzeichnisse, die spezifisch für optionale Python-Komponenten sind, die noch nicht in Pakete konvertiert wurden, wurden in einen Namen mit dem Präfix "lib-" umbenannt. Das Verzeichnis dos_8x3 wurde in dos-8x3 umbenannt. Die folgenden Tabellen zeigen alle umbenannten Verzeichnisse

Alter NameNeuer Name
tkinterlib-tk
stdwinlib-stdwin
sharedmoduleslib-dynload
dos_8x3dos-8x3
aix3plat-aix3
aix4plat-aix4
freebsd2plat-freebsd2
genericplat-generic
irix5plat-irix5
irix6plat-irix6
linux1plat-linux1
linux2plat-linux2
next3plat-next3
sunos4plat-sunos4
sunos5plat-sunos5
winplat-win
testentesten

Beachten Sie, dass das Testverzeichnis nicht umbenannt wird. Es ist jetzt ein Paket. Um es aufzurufen, verwenden Sie eine Anweisung wie import test.autotest.

Sonstiges

XXX Ich hatte noch keine Zeit, Diskussionen zu den folgenden Punkten zu schreiben
  • Neue imp-Funktionen.
  • Zukünftige Richtungen.
  • Zukunft von ihooks.
  • Zukünftige Umorganisation des Namensraums.
  • Was tun mit ni? Deaktivieren und oldni erzwingen?

    Änderungen von ni

    Die folgenden Features von ni wurden nicht exakt dupliziert. Ignorieren Sie diesen Abschnitt, es sei denn, Sie verwenden derzeit das ni-Modul und möchten zum eingebauten Paket-Support migrieren.

    __domain__ fallen gelassen

    Standardmäßig suchte ni, wenn ein Untermodul des Pakets A.B.C ein Modul X importierte, nach A.B.C.X, A.B.X, A.X und X, in dieser Reihenfolge. Dies wurde durch die Variable __domain__ im Paket definiert, die auf eine Liste von zu durchsuchenden Paketnamen gesetzt werden konnte. Dieses Feature ist im eingebauten Paket-Support weggefallen. Stattdessen sucht die Suche immer zuerst nach A.B.C.X und dann nach X. (Dies ist eine Umkehrung des "Zwei-Geltungsbereiche"-Ansatzes, der an anderer Stelle in Python erfolgreich zur Namensraumauflösung verwendet wird.)

    __ fallen gelassen

    Mit ni konnten Pakete explizite "relative" Modulnamen mit dem Sondernamen "__" (zwei Unterstriche) verwenden. Zum Beispiel können Module im Paket A.B.C Module referenzieren, die im Paket A.B.K definiert sind, über Namen der Form __.__.K.module. Dieses Feature wurde wegen seiner begrenzten Nutzung und schlechten Lesbarkeit gestrichen.

    Inkompatible Semantik für __init__

    Mit ni wurde die __init__.py-Datei innerhalb eines Pakets (falls vorhanden) als Standarduntermodul des Pakets importiert. Die integrierte Paketunterstützung lädt stattdessen die __init__.py-Datei in den Namensraum des Pakets. Das bedeutet, wenn __init__.py im Paket A einen Namen x definiert, kann er ohne weitere Anstrengung als A.x referenziert werden. Mit ni hätte __init__.py eine Zuweisung der Form __.x = x enthalten müssen, um denselben Effekt zu erzielen.

    Außerdem erfordert die neue Paketunterstützung ein __init__-Modul; unter ni war es optional. Dies ist eine Änderung, die in Python 1.5b1 eingeführt wurde; sie soll Verzeichnisse mit gängigen Namen wie "string" daran hindern, gültige Module, die später im Modul-Suchpfad vorkommen, versehentlich zu verdecken.

    Pakete, die abwärtskompatibel mit ni sein sollen, können testen, ob die spezielle Variable __ existiert, z. B.

    # Define a function to be visible at the package level
    def f(...): ...
    
    try:
        __
    except NameError:    # new built-in package support
        pass
    else:                # backwards compatibility for ni
        __.f = f