Was ist der Unterschied zwischen einem Python-Modul und einem Python-Paket?

576

Was ist der Unterschied zwischen einem Python-Modul und einem Python-Paket?

Siehe auch: Was ist der Unterschied zwischen "Paket" und "Modul" (für andere Sprachen)

Dave
quelle
9
Ich könnte mich irren, aber für mich: Ein Modul ist im Grunde eine Python-Datei. Ein Paket ist ein Ordner mit einer Reihe von Modulen (Python-Dateien).
lc2817
36
Um als Paket betrachtet zu werden, muss dieser Ordner eine __init__.pyDatei enthalten .
Giulio Piancastelli
@ lc2817: Dies ist der häufigste Fall, aber es ist nicht erforderlich, dass ein Modul aus einem Dateisystem geladen wird, z. B. siehe from plumbum.cmd import lsImplementierung
jfs
4
@ GiulioPiancastelli: In Python 3.3+ verwenden Namespace-Pakete nicht__init__.py
jfs
Wie unterscheidet die Community zwischen Python-Paketen und Paketen, mit denen Python-Komponenten wie PyPI / Wheels / etc verteilt werden? Die beiden scheinen mir unterschiedliche Anwendungen des Wortes "Paket" zu sein.
DavidA

Antworten:

373

Ein Modul ist eine einzelne Datei (oder Dateien), die unter einem Import importiert und verwendet werden. z.B

import my_module

Ein Paket ist eine Sammlung von Modulen in Verzeichnissen, die eine Pakethierarchie angeben.

from my_package.timing.danger.internets import function_of_love

Dokumentation für Module

Einführung in Pakete

Jakob Bowyer
quelle
54
Wenn Sie sagen: "Ein Modul ist eine einzelne Datei (oder Dateien), die unter einem Import importiert werden", können Sie die Situation erklären, in der ein Modul aus mehr als einer Datei besteht? Oder verstehe ich falsch, was du meinst?
Benutzer
5
Sie benötigen keine Datei, um ein Modul zu erstellen. Sie können beispielsweise ein Modul aus einer Zip-Datei importieren. Gleiches gilt für Pakete. In Python gibt es nur eine Klasse für Module / Pakete. Das Paket ist nur ein Modul mit einem __path__Attribut.
JFS
33
Pakete sind auch Module . Sie sind nur anders verpackt; Sie werden durch die Kombination eines Verzeichnisses plus einer __init__.pyDatei gebildet. Sie sind Module, die andere Module enthalten können.
Martijn Pieters
15
@Jacquot sicher, siehe Das Importsystem in der Referenzdokumentation: Es ist wichtig zu beachten, dass alle Pakete Module sind .
Martijn Pieters
6
@Jacquot: und das Glossar zu "package" : Ein Python-Modul, das Submodule oder rekursiv Subpakete enthalten kann. Technisch gesehen ist ein Paket ein Python-Modul mit einem __path__Attribut.
Martijn Pieters
556

Jede Python-Datei ist ein Modul , dessen Name der Basisname der Datei ohne die .pyErweiterung ist. Ein Paket ist eine Sammlung von Python-Modulen: Während ein Modul eine einzelne Python-Datei ist, ist ein Paket ein Verzeichnis von Python-Modulen, die eine zusätzliche __init__.pyDatei enthalten, um ein Paket von einem Verzeichnis zu unterscheiden, das zufällig eine Reihe von Python-Skripten enthält. Pakete können bis zu einer beliebigen Tiefe verschachtelt werden, vorausgesetzt, die entsprechenden Verzeichnisse enthalten eine eigene __init__.pyDatei.

Die Unterscheidung zwischen Modul und Paket scheint nur auf Dateisystemebene zu gelten. Wenn Sie ein Modul oder ein Paket importieren, ist das entsprechende von Python erstellte Objekt immer vom Typ module. Beachten Sie jedoch, dass beim Importieren eines Pakets nur Variablen / Funktionen / Klassen in der __init__.pyDatei dieses Pakets direkt sichtbar sind, keine Unterpakete oder Module. Betrachten Sie als Beispiel das xmlPaket in der Python-Standardbibliothek: Das xmlVerzeichnis enthält eine __init__.pyDatei und vier Unterverzeichnisse. Das Unterverzeichnis etreeenthält eine __init__.pyDatei und unter anderem eine ElementTree.pyDatei. Sehen Sie, was passiert, wenn Sie versuchen, Pakete / Module interaktiv zu importieren:

>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>

In Python gibt es auch integrierte Module, z. B. sys, die in C geschrieben sind, aber ich glaube nicht, dass Sie diese in Ihrer Frage berücksichtigen wollten.

Giulio Piancastelli
quelle
9
Vielen Dank, dass Sie ausdrücklich erwähnt haben, dass das entsprechende von Python erstellte Objekt immer vom Typ ist module. Ich bin gerade dabei, einen Debugger zu schreiben, und habe mir Sorgen gemacht, dass mein Debugger nicht korrekt gesagt hat, dass meine Pakete modules sind.
ArtOfWarfare
8
@ jolvi Python-Dateien mit einem Dateinamen, der Bindestriche enthält, können weiterhin als Module importiert werden, nur nicht mit der üblichen importAnweisung, da Bindestriche in Python-Bezeichnern nicht zulässig sind. Verwenden Sie importlib.import_module()stattdessen.
Giulio Piancastelli
2
@jolvi bin ich nicht. Wo in meinem Kommentar liest du das? Ich sage nur, wenn Sie eine Python-Datei mit Bindestrichen im Namen haben oder darauf stoßen, können Sie sie trotzdem als Modul importieren. Ich mache keine Aussage über die bevorzugte Art, eine Python-Datei zu benennen. Ich bin sicher, dass Sie das woanders finden können: Es wird normalerweise dringend empfohlen, Bindestriche zugunsten von Unterstrichen zu vermeiden.
Giulio Piancastelli
3
Da ich neu in Python bin, sind Unterpakete oder Module beim Importieren des übergeordneten Pakets standardmäßig nicht verfügbar, was mich zum Stolpern gebracht hat. Gibt es dafür einen besonderen Grund? Und gibt es ein gemeinsames Muster , wie man macht Teilpakete oder Module zur Verfügung (über ihre voll qualifizierten Namen) , wenn das Paket Mutter importieren?
Sschuberth
2
@sschuberth Importieren Sie einfach Unterpakete in init .py eines übergeordneten Pakets.
Anna
33

Aus dem Python-Glossar :

Es ist wichtig zu beachten, dass alle Pakete Module sind, aber nicht alle Module Pakete. Oder anders ausgedrückt: Pakete sind nur eine besondere Art von Modul. Insbesondere wird jedes Modul, das ein __path__Attribut enthält , als Paket betrachtet.

Python-Dateien mit einem Bindestrich im Namen my-file.pykönnen nicht mit einer einfachen importAnweisung importiert werden . Code-weise import my-fileist das gleiche, import my - filewas eine Ausnahme auslöst. Solche Dateien werden besser als Skripte charakterisiert, während importierbare Dateien Module sind .

jolvi
quelle
23

Denken Sie zunächst daran, dass ein Modul in seiner genauen Definition ein Objekt im Speicher eines Python-Interpreters ist, das häufig durch Lesen einer oder mehrerer Dateien von der Festplatte erstellt wird. Während wir eine Datenträgerdatei wie a/b/c.pyein "Modul" informell aufrufen können , wird sie erst dann zu einer, wenn sie mit Informationen aus mehreren anderen Quellen (z. B. sys.path) kombiniert wird , um das Modulobjekt zu erstellen.

(Beachten Sie beispielsweise, dass zwei Module mit unterschiedlichen Namen abhängig von sys.pathund anderen Einstellungen aus derselben Datei geladen werden können. Genau dies geschieht mit python -m my.moduleeinem import my.moduleim Interpreter gefolgt von einem ; es werden zwei Modulobjekte erstellt __main__und my.modulebeide erstellt aus derselben Datei auf der Festplatte , my/module.py.)

Ein Paket ist ein Modul, das Submodule (einschließlich Subpakete) enthalten kann. Dies können nicht alle Module. Erstellen Sie als Beispiel eine kleine Modulhierarchie:

$ mkdir -p a/b
$ touch a/b/c.py

Stellen Sie sicher, dass sich keine anderen Dateien unter befinden a. Starten Sie einen Python 3.4- oder späteren Interpreter (z. B. mit python3 -i) und überprüfen Sie die Ergebnisse der folgenden Anweisungen:

import a
a                 <module 'a' (namespace)>
a.b               AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b               <module 'a.b' (namespace)>
a.b.c             <module 'a.b.c' from '/home/cjs/a/b/c.py'>

Module aund a.bsind Pakete (in der Tat eine bestimmte Art von Paket, das als "Namespace-Paket" bezeichnet wird, obwohl wir uns hier nicht darum kümmern müssen). Das Modul a.b.cist jedoch kein Paket. Wir können dies demonstrieren, indem wir a/b.pyder obigen Verzeichnisstruktur eine weitere Datei hinzufügen und einen neuen Interpreter starten:

import a.b.c
 ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a                 <module 'a' (namespace)>
a.__path__        _NamespacePath(['/.../a'])
a.b               <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__      AttributeError: 'module' object has no attribute '__path__'

Python stellt sicher, dass alle übergeordneten Module geladen werden, bevor ein untergeordnetes Modul geladen wird. Darüber , dass findet a/ein Verzeichnis ist , und schafft so ein Namespace - Paket a, und das a/b.pyist eine Datei Python Quelle , die es lädt und verwendet ein (nicht-Paket) Modul zu erstellen a.b. Zu diesem Zeitpunkt können Sie kein Modul haben, a.b.cda a.bes sich nicht um ein Paket handelt und daher keine Submodule haben können.

Sie können hier auch sehen, dass das Paketmodul aein __path__Attribut hat (Pakete müssen dieses haben), das Nicht-Paketmodul a.bjedoch nicht.

cjs
quelle
1
Wenn Sie dies noch nicht getan haben, gehen Sie zurück und arbeiten Sie die Beispiele in dieser Antwort durch.
Donal Lafferty
2

Eine späte Antwort, noch eine Definition:

Ein Paket wird durch eine importierte Top-Entität dargestellt, die entweder ein in sich geschlossenes Modul oder das __init__.pySpezialmodul als Top-Entität aus einer Reihe von Modulen innerhalb einer Unterverzeichnisstruktur sein kann.

Ein Paket ist also physisch eine Verteilungseinheit, die ein oder mehrere Module bereitstellt.

ein Hinweis
quelle
1
Ich habe das Gefühl, dass es in Python zwei Definitionen für Pakete gibt, die sich unterscheiden. Ihre Antwort scheint sie miteinander zu kombinieren. Genau genommen ist ein Python-Paket ein Verzeichnis mit einem darin enthaltenen __init__.pyModul. Wenn Sie jedoch über Verteilungseinheiten sprechen (üblicherweise über PyPI), ist dies ein ganz anderer Pakettyp (normalerweise definiert durch das Vorhandensein von setup.py). Ich finde diese beiden Verwendungen des Begriffs packageverwirrend und habe mit einigen Python-Anfängern gesprochen, die ihn äußerst verwirrend finden.
DavidA
@davidA, Es ist nicht nur so, wie du dich fühlst. Es ist kodifiziert: packaging.python.org/glossary/#term-distribution-package (Danke für die Klärung, auch!)
Lorem Ipsum
0

Das Paket ist auch ein Modul, das andere Module, "einfache dateibasierte Module und Pakete (Unterpaket)" enthalten kann. Der Code für den Pakettyp des Moduls wird in die __init__.pyDatei aufgenommen.

import pack1
print(type(pack1))

Während Module eine einfache Datei sind, die Funktionen, Klassen, ausführbaren Code usw. enthalten kann, verhält sie sich nach dem Importieren eines Moduls wie ein Objekt, mit dem Sie auf die im Modul definierten Bezeichner zugreifen können.

Anil kumar
quelle