6. Module

Wenn Sie den Python-Interpreter beenden und ihn erneut aufrufen, gehen die von Ihnen getroffenen Definitionen (Funktionen und Variablen) verloren. Wenn Sie also ein etwas längeres Programm schreiben möchten, ist es besser, einen Texteditor zu verwenden, um die Eingaben für den Interpreter vorzubereiten und diese Datei als Eingabe zu verwenden. Dies wird als Erstellen eines Skripts bezeichnet. Wenn Ihr Programm länger wird, möchten Sie es möglicherweise aus Wartungsgründen in mehrere Dateien aufteilen. Möglicherweise möchten Sie auch eine praktische Funktion verwenden, die Sie in mehreren Programmen geschrieben haben, ohne ihre Definition in jedes Programm zu kopieren.

Um dies zu unterstützen, bietet Python eine Möglichkeit, Definitionen in einer Datei abzulegen und sie in einem Skript oder einer interaktiven Interpreter-Instanz zu verwenden. Eine solche Datei wird als Modul bezeichnet; Definitionen aus einem Modul können in andere Module oder in das Hauptmodul (die Sammlung von Variablen, auf die Sie in einem auf oberster Ebene ausgeführten Skript und im Taschenrechner-Modus zugreifen können) importiert werden.

Ein Modul ist eine Datei, die Python-Definitionen und -Anweisungen enthält. Der Dateiname ist der Modulname mit dem angehängten Suffix .py. Innerhalb eines Moduls ist der Name des Moduls (als Zeichenkette) als Wert der globalen Variablen __name__ verfügbar. Verwenden Sie beispielsweise Ihren bevorzugten Texteditor, um eine Datei namens fibo.py im aktuellen Verzeichnis mit folgendem Inhalt zu erstellen

# Fibonacci numbers module

def fib(n):
    """Write Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()

def fib2(n):
    """Return Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while a < n:
        result.append(a)
        a, b = b, a+b
    return result

Geben Sie nun den Python-Interpreter ein und importieren Sie dieses Modul mit dem folgenden Befehl

>>> import fibo

Dies fügt die Namen der in fibo definierten Funktionen nicht direkt in den aktuellen Namensraum ein (weitere Einzelheiten finden Sie in Python Scopes und Namensräume); es fügt nur den Modulnamen fibo dort hinzu. Mit dem Modulnamen können Sie auf die Funktionen zugreifen

>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'

Wenn Sie eine Funktion oft verwenden möchten, können Sie ihr einen lokalen Namen zuweisen

>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

6.1. Mehr über Module

Ein Modul kann ausführbare Anweisungen sowie Funktionsdefinitionen enthalten. Diese Anweisungen sollen das Modul initialisieren. Sie werden nur beim ersten Auftreten des Modulnamens in einer Importanweisung ausgeführt. [1] (Sie werden auch ausgeführt, wenn die Datei als Skript ausgeführt wird.)

Jedes Modul hat seinen eigenen privaten Namensraum, der als globaler Namensraum für alle im Modul definierten Funktionen dient. So kann der Autor eines Moduls globale Variablen im Modul verwenden, ohne sich Gedanken über versehentliche Konflikte mit den globalen Variablen eines Benutzers machen zu müssen. Andererseits können Sie, wenn Sie wissen, was Sie tun, auf die globalen Variablen eines Moduls mit derselben Notation zugreifen wie auf seine Funktionen, nämlich modulname.elementname.

Module können andere Module importieren. Es ist üblich, aber nicht zwingend erforderlich, alle import-Anweisungen am Anfang eines Moduls (oder Skripts) zu platzieren. Die importierten Modulnamen werden, wenn sie auf der obersten Ebene eines Moduls platziert werden (außerhalb von Funktionen oder Klassen), zum globalen Namensraum des Moduls hinzugefügt.

Es gibt eine Variante der import-Anweisung, die Namen aus einem Modul direkt in den Namensraum des importierenden Moduls importiert. Zum Beispiel

>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Dies führt den Modulnamen, aus dem importiert wird, nicht in den lokalen Namensraum ein (im Beispiel ist fibo also nicht definiert).

Es gibt sogar eine Variante, um alle Namen zu importieren, die ein Modul definiert

>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Dies importiert alle Namen außer denen, die mit einem Unterstrich (_) beginnen. In den meisten Fällen verwenden Python-Programmierer diese Funktion nicht, da sie eine unbekannte Menge von Namen in den Interpreter einführt und möglicherweise Dinge überschreibt, die Sie bereits definiert haben.

Beachten Sie, dass die Praxis, * aus einem Modul oder Paket zu importieren, im Allgemeinen verpönt ist, da sie oft zu schlecht lesbarem Code führt. Es ist jedoch in Ordnung, sie in interaktiven Sitzungen zu verwenden, um Tipparbeit zu sparen.

Wenn auf den Modulnamen as folgt, wird der nach as stehende Name direkt an das importierte Modul gebunden.

>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Dies ist im Wesentlichen der gleiche Import wie import fibo, mit dem einzigen Unterschied, dass es als fib verfügbar ist.

Dies kann auch bei der Verwendung von from mit ähnlichen Effekten verwendet werden

>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377

Hinweis

Aus Effizienzgründen wird jedes Modul nur einmal pro Interpreter-Sitzung importiert. Wenn Sie also Ihre Module ändern, müssen Sie den Interpreter neu starten – oder, wenn es nur ein Modul ist, das Sie interaktiv testen möchten, verwenden Sie importlib.reload(), z. B. import importlib; importlib.reload(modulename).

6.1.1. Module als Skripte ausführen

Wenn Sie ein Python-Modul mit

python fibo.py <arguments>

ausführen, wird der Code im Modul ausgeführt, so als hätten Sie es importiert, aber mit __name__ auf "__main__" gesetzt. Das bedeutet, dass Sie durch Hinzufügen dieses Codes am Ende Ihres Moduls

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

die Datei sowohl als Skript als auch als importierbares Modul verwendbar machen können, da der Code, der die Kommandozeile analysiert, nur ausgeführt wird, wenn das Modul als "Haupt"-Datei ausgeführt wird

$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34

Wenn das Modul importiert wird, wird der Code nicht ausgeführt

>>> import fibo
>>>

Dies wird oft entweder verwendet, um eine bequeme Benutzeroberfläche für ein Modul bereitzustellen, oder zu Testzwecken (das Ausführen des Moduls als Skript führt eine Testsuite aus).

6.1.2. Der Modul-Suchpfad

Wenn ein Modul namens spam importiert wird, sucht der Interpreter zuerst nach einem integrierten Modul mit diesem Namen. Diese Modulnamen sind in sys.builtin_module_names aufgeführt. Wenn es nicht gefunden wird, sucht es dann nach einer Datei namens spam.py in einer Liste von Verzeichnissen, die durch die Variable sys.path gegeben ist. sys.path wird aus diesen Speicherorten initialisiert

  • Das Verzeichnis, das das Eingabeskript enthält (oder das aktuelle Verzeichnis, wenn keine Datei angegeben ist).

  • PYTHONPATH (eine Liste von Verzeichnisnamen mit derselben Syntax wie die Shell-Variable PATH).

  • Der installationsabhängige Standard (konventionsgemäß einschließlich eines site-packages-Verzeichnisses, das vom site-Modul behandelt wird).

Weitere Details finden Sie unter Die Initialisierung des Modul-Suchpfads sys.path.

Hinweis

Auf Dateisystemen, die Symlinks unterstützen, wird das Verzeichnis, das das Eingabeskript enthält, nach Verfolgung des Symlinks ermittelt. Mit anderen Worten, das Verzeichnis, das den Symlink enthält, wird dem Modul-Suchpfad **nicht** hinzugefügt.

Nach der Initialisierung können Python-Programme sys.path ändern. Das Verzeichnis, das das ausgeführte Skript enthält, wird am Anfang des Suchpfads platziert, vor dem Pfad der Standardbibliothek. Das bedeutet, dass Skripte in diesem Verzeichnis anstelle von Modulen mit demselben Namen im Bibliotheksverzeichnis geladen werden. Dies ist ein Fehler, es sei denn, die Ersetzung ist beabsichtigt. Siehe Abschnitt Standardmodule für weitere Informationen.

6.1.3. „Kompilierte“ Python-Dateien

Um das Laden von Modulen zu beschleunigen, speichert Python die kompilierte Version jedes Moduls im Verzeichnis __pycache__ unter dem Namen modul.version.pyc, wobei die Version das Format der kompilierten Datei kodiert; sie enthält im Allgemeinen die Python-Versionsnummer. Zum Beispiel wird in CPython-Version 3.3 die kompilierte Version von spam.py als __pycache__/spam.cpython-33.pyc zwischengespeichert. Diese Namenskonvention ermöglicht es kompilierten Modulen von verschiedenen Releases und verschiedenen Python-Versionen, nebeneinander zu existieren.

Python überprüft das Änderungsdatum des Quellcodes gegen die kompilierte Version, um festzustellen, ob sie veraltet ist und neu kompiliert werden muss. Dies ist ein völlig automatischer Prozess. Außerdem sind die kompilierten Module plattformunabhängig, sodass dieselbe Bibliothek zwischen Systemen mit unterschiedlichen Architekturen geteilt werden kann.

Python überprüft den Cache in zwei Fällen nicht. Erstens kompiliert es immer neu und speichert das Ergebnis nicht für das Modul, das direkt von der Kommandozeile geladen wird. Zweitens prüft es den Cache nicht, wenn keine Quellmodul vorhanden ist. Um eine Distribution ohne Quellcode (nur kompiliert) zu unterstützen, muss das kompilierte Modul im Quellverzeichnis liegen und es darf kein Quellmodul vorhanden sein.

Einige Tipps für Experten

  • Sie können die Schalter -O oder -OO auf der Python-Kommandozeile verwenden, um die Größe eines kompilierten Moduls zu reduzieren. Der Schalter -O entfernt assert-Anweisungen, der Schalter -OO entfernt sowohl assert-Anweisungen als auch __doc__-Strings. Da einige Programme davon abhängen könnten, diese verfügbar zu haben, sollten Sie diese Option nur verwenden, wenn Sie wissen, was Sie tun. „Optimierte“ Module haben ein opt-Tag und sind normalerweise kleiner. Zukünftige Versionen können die Auswirkungen der Optimierung ändern.

  • Ein Programm läuft nicht schneller, wenn es aus einer .pyc-Datei gelesen wird als aus einer .py-Datei; das Einzige, was bei .pyc-Dateien schneller ist, ist die Geschwindigkeit, mit der sie geladen werden.

  • Das Modul compileall kann .pyc-Dateien für alle Module in einem Verzeichnis erstellen.

  • Mehr Details zu diesem Prozess, einschließlich eines Flussdiagramms der Entscheidungen, finden Sie in PEP 3147.

6.2. Standardmodule

Python wird mit einer Bibliothek von Standardmodulen geliefert, die in einem separaten Dokument, der Python Library Reference („Library Reference“ im Folgenden), beschrieben sind. Einige Module sind in den Interpreter integriert; diese bieten Zugriff auf Operationen, die nicht Teil des Kerns der Sprache sind, aber dennoch integriert sind, entweder aus Effizienzgründen oder um Zugriff auf Betriebssystemprimitive wie Systemaufrufe zu ermöglichen. Die Menge solcher Module ist eine Konfigurationsoption, die auch vom zugrunde liegenden Plattforms abhängt. Zum Beispiel wird das Modul winreg nur auf Windows-Systemen bereitgestellt. Ein besonderes Modul verdient einige Aufmerksamkeit: sys, das in jeden Python-Interpreter integriert ist. Die Variablen sys.ps1 und sys.ps2 definieren die Zeichenketten, die als primäre und sekundäre Eingabeaufforderungen verwendet werden

>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>

Diese beiden Variablen sind nur definiert, wenn der Interpreter im interaktiven Modus ist.

Die Variable sys.path ist eine Liste von Zeichenketten, die den Suchpfad des Interpreters für Module bestimmt. Sie wird mit einem Standardpfad initialisiert, der aus der Umgebungsvariable PYTHONPATH stammt oder aus einem integrierten Standardwert, wenn PYTHONPATH nicht gesetzt ist. Sie können ihn mit Standardlistenoperationen ändern

>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')

6.3. Die Funktion dir()

Die eingebaute Funktion dir() wird verwendet, um herauszufinden, welche Namen ein Modul definiert. Sie gibt eine sortierte Liste von Zeichenketten zurück

>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
 '__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
 '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
 '_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
 '_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
 'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
 'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
 'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
 'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
 'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
 'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
 'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
 'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
 'warnoptions']

Ohne Argumente listet dir() die Namen auf, die Sie derzeit definiert haben

>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']

Beachten Sie, dass alle Arten von Namen aufgelistet werden: Variablen, Module, Funktionen usw.

dir() listet die Namen von integrierten Funktionen und Variablen nicht auf. Wenn Sie eine Liste davon haben möchten, sind diese im Standardmodul builtins definiert

>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
 'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
 'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
 'NotImplementedError', 'OSError', 'OverflowError',
 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
 '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
 'zip']

6.4. Pakete

Pakete sind eine Möglichkeit, den Python-Modul-Namensraum mithilfe von „gepunkteten Modulnamen“ zu strukturieren. Beispielsweise bezeichnet der Modulname A.B ein Untermodul namens B in einem Paket namens A. So wie die Verwendung von Modulen die Autoren verschiedener Module davon befreit, sich über die globalen Variablennamen anderer Sorgen zu machen, so befreit die Verwendung von gepunkteten Modulnamen die Autoren von Multi-Modul-Paketen wie NumPy oder Pillow von der Sorge um ihre Modulnamen.

Angenommen, Sie möchten eine Sammlung von Modulen (ein „Paket“) für die einheitliche Verarbeitung von Sounddateien und Audiodaten 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 für die Konvertierung zwischen den verschiedenen Dateiformaten erstellen und warten müssen. Es gibt auch viele verschiedene Operationen, die Sie mit Audiodaten durchführen möchten (wie Mischen, Hinzufügen von Echo, Anwenden einer Equalizer-Funktion, Erstellen eines künstlichen Stereoeffekts), sodass Sie außerdem einen endlosen Strom von Modulen zum Ausführen dieser Operationen schreiben werden. Hier ist eine mögliche Struktur für Ihr Paket (ausgedrückt als hierarchisches Dateisystem)

sound/                          Top-level package
      __init__.py               Initialize the sound package
      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
              ...

Beim Importieren des Pakets durchsucht Python die Verzeichnisse in sys.path nach dem Paketunterverzeichnis.

Die Dateien __init__.py sind erforderlich, damit Python Verzeichnisse, die die Datei enthalten, als Pakete behandelt (es sei denn, Sie verwenden ein Namensraum-Paket, eine relativ fortgeschrittene Funktion). Dies verhindert, dass Verzeichnisse mit einem gemeinsamen Namen wie string gültige Module, die später im Modul-Suchpfad vorkommen, unbeabsichtigt verbergen. Im einfachsten Fall kann __init__.py einfach eine leere Datei sein, aber sie kann auch Initialisierungscode für das Paket ausführen oder die Variable __all__ festlegen, die später beschrieben wird.

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.

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)

Eine alternative Möglichkeit, das Untermodul zu importieren, ist

from sound.effects import echo

Dies lädt ebenfalls das Untermodul echo und macht es ohne seinen Paketpräfix verfügbar, sodass es wie folgt verwendet werden kann

echo.echofilter(input, output, delay=0.7, atten=4)

Eine weitere Variante ist der direkte Import der gewünschten Funktion oder Variable

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 bei Verwendung von from package import item das Element 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 import-Anweisung prüft zuerst, ob das Element im Paket definiert ist; wenn nicht, nimmt sie an, dass es sich um ein Modul handelt, und versucht, es zu laden. Wenn sie es nicht findet, wird eine ImportError-Ausnahme ausgelöst.

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

6.4.1. Importieren von * Aus einem Paket

Was passiert nun, wenn der Benutzer from sound.effects import * schreibt? Idealerweise würde man hoffen, dass dies irgendwie auf das Dateisystem zugreift, feststellt, welche Untermodule im Paket vorhanden sind, und sie alle importiert. Dies könnte lange dauern und das Importieren von Untermodulen könnte unerwünschte Nebeneffekte haben, die nur auftreten sollten, wenn das Untermodul explizit importiert wird.

Die einzige Lösung besteht darin, dass der Paketautor einen expliziten Index des Pakets bereitstellt. Die import-Anweisung verwendet die folgende Konvention: Wenn der Code der __init__.py-Datei eines Pakets eine Liste namens __all__ definiert, wird diese als Liste der Modulnamen betrachtet, 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 aktuell zu halten. Paketautoren können sich auch entscheiden, sie nicht zu unterstützen, wenn sie keinen Nutzen im Importieren von * aus ihrem Paket sehen. Zum Beispiel könnte die Datei sound/effects/__init__.py folgenden Code enthalten

__all__ = ["echo", "surround", "reverse"]

Dies würde bedeuten, dass from sound.effects import * die drei genannten Untermodule des Pakets sound.effects importieren würde.

Beachten Sie, dass Untermodule durch lokal definierte Namen überschattet werden können. Wenn Sie beispielsweise eine reverse-Funktion in die Datei sound/effects/__init__.py einfügen, würde from sound.effects import * nur die beiden Untermodule echo und surround importieren, aber **nicht** das Untermodul reverse, da es durch die lokal definierte reverse-Funktion überschattet wird

__all__ = [
    "echo",      # refers to the 'echo.py' file
    "surround",  # refers to the 'surround.py' file
    "reverse",   # !!! refers to the 'reverse' function now !!!
]

def reverse(msg: str):  # <-- this name shadows the 'reverse.py' submodule
    return msg[::-1]    #     in the case of a 'from sound.effects import *'

Wenn __all__ nicht definiert ist, importiert die Anweisung from sound.effects import * **nicht** alle Untermodule des Pakets sound.effects in den aktuellen Namensraum; sie stellt nur sicher, dass das Paket sound.effects importiert wurde (möglicherweise mit Ausführung von Initialisierungscode in __init__.py) und importiert dann alle Namen, die im Paket definiert sind. Dies schließt alle Namen ein, die von __init__.py definiert (und Untermodule explizit geladen) wurden. Es schließt auch alle Untermodule des Pakets ein, die durch vorherige import-Anweisungen explizit geladen wurden. Betrachten Sie diesen Code

import sound.effects.echo
import sound.effects.surround
from sound.effects import *

In diesem Beispiel werden die Module echo und surround im 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.)

Obwohl bestimmte Module so konzipiert sind, dass sie nur Namen exportieren, die bestimmten Mustern folgen, wenn Sie import * verwenden, gilt dies in Produktionscode immer noch als schlechte Praxis.

Denken Sie daran, dass es nichts Falsches daran gibt, from package import spezifisches_untermodul zu verwenden! Tatsächlich ist dies die empfohlene Notation, es sei denn, das importierende Modul muss Untermodule mit demselben Namen aus verschiedenen Paketen verwenden.

6.4.2. Referenzen innerhalb von Paketen

Wenn Pakete in Unterpakete strukturiert sind (wie beim sound-Paket im Beispiel), können Sie absolute Importe verwenden, um sich auf Untermodule von Geschwisterpaketen zu beziehen. Zum Beispiel muss das Modul sound.filters.vocoder das Modul echo im Paket sound.effects verwenden, und kann dafür from sound.effects import echo verwenden.

Sie können auch relative Importe mit der Importanweisung from module import name verwenden. Diese Importe verwenden führende Punkte, um die beteiligten aktuellen und übergeordneten Pakete im relativen Import anzugeben. Aus dem Modul surround könnten Sie beispielsweise Folgendes verwenden

from . import echo
from .. import formats
from ..filters import equalizer

Beachten Sie, dass relative Importe auf dem Namen des Pakets des aktuellen Moduls basieren. Da das Hauptmodul kein Paket hat, müssen Module, die als Hauptmodul einer Python-Anwendung verwendet werden sollen, immer absolute Importe verwenden.

6.4.3. Pakete in mehreren Verzeichnissen

Pakete unterstützen ein weiteres spezielles Attribut, __path__. Dies wird initialisiert, um eine Sequenz von Zeichenketten zu sein, die den Namen des Verzeichnisses enthält, das die __init__.py des Pakets enthält, bevor der Code in dieser Datei ausgeführt wird. Diese Variable kann geändert werden; dies beeinflusst zukünftige Suchen nach Modulen und Unterpaketen, die im Paket enthalten sind.

Diese Funktion wird zwar nicht oft benötigt, kann aber verwendet werden, um die Menge der in einem Paket gefundenen Module zu erweitern.

Fußnoten