Quelle est la différence entre un module Python et un package Python?

577

Quelle est la différence entre un module Python et un package Python?

Voir aussi: Quelle est la différence entre "package" et "module" (pour les autres langues)

Dave
la source
9
Je me trompe peut-être mais pour moi: un module est essentiellement un fichier python. Un package est un dossier avec un tas de modules (fichiers python).
lc2817
36
Pour être considéré comme un package, ce dossier doit contenir un __init__.pyfichier.
Giulio Piancastelli
@ lc2817: c'est le cas le plus courant mais il n'est pas nécessaire de charger un module à partir d'un système de fichiers par exemple, voir from plumbum.cmd import lsimplémentation
jfs
4
@GiulioPiancastelli: Dans Python 3.3+, les packages d'espace de noms n'utilisent pas__init__.py
jfs
Comment la communauté fait-elle la différence entre les packages Python et les packages utilisés pour distribuer des composants Python tels que PyPI / roues / etc? Les deux me semblent être des applications différentes du mot "package".
davidA

Réponses:

372

Un module est un ou plusieurs fichiers qui sont importés sous une seule importation et utilisés. par exemple

import my_module

Un package est une collection de modules dans des répertoires qui donnent une hiérarchie de package.

from my_package.timing.danger.internets import function_of_love

Documentation pour les modules

Introduction aux packages

Jakob Bowyer
la source
54
Lorsque vous dites: "Un module est un seul fichier (ou des fichiers) qui sont importés sous une seule importation", pouvez-vous expliquer la situation où un module est composé de plusieurs fichiers? Ou suis-je en train de mal comprendre ce que vous voulez dire?
User
6
Vous n'avez pas besoin d'un fichier pour créer un module, par exemple, vous pouvez importer un module à partir d'un fichier zip. Idem pour les packages. Il n'y a qu'une seule classe pour les modules / packages en Python. Le package est juste un module avec un __path__attribut.
jfs
33
Les packages sont également des modules . Ils sont simplement emballés différemment; ils sont formés par la combinaison d'un répertoire et d'un __init__.pyfichier. Ce sont des modules qui peuvent contenir d'autres modules.
Martijn Pieters
15
@Jacquot bien sûr, voir Le système d'importation dans la documentation de référence: Il est important de garder à l'esprit que tous les packages sont des modules .
Martijn Pieters
6
@Jacquot: et le glossaire sur «package» : Un module Python qui peut contenir des sous-modules ou récursivement, des sous-packages. Techniquement, un package est un module Python avec un __path__attribut.
Martijn Pieters
556

Tout fichier Python est un module , son nom étant le nom de base du fichier sans l' .pyextension. Un package est une collection de modules Python: alors qu'un module est un fichier Python unique, un package est un répertoire de modules Python contenant un __init__.pyfichier supplémentaire , pour distinguer un package d'un répertoire qui se trouve juste contenir un tas de scripts Python. Les packages peuvent être imbriqués à n'importe quelle profondeur, à condition que les répertoires correspondants contiennent leur propre __init__.pyfichier.

La distinction entre module et package semble se maintenir uniquement au niveau du système de fichiers. Lorsque vous importez un module ou un package, l'objet correspondant créé par Python est toujours de type module. Notez cependant que lorsque vous importez un package, seules les variables / fonctions / classes du __init__.pyfichier de ce package sont directement visibles, pas les sous-packages ou modules. À titre d'exemple, considérons le xmlpackage dans la bibliothèque standard Python: son xmlrépertoire contient un __init__.pyfichier et quatre sous-répertoires; le sous-répertoire etreecontient un __init__.pyfichier et, entre autres, un ElementTree.pyfichier. Voyez ce qui se passe lorsque vous essayez d'importer de manière interactive des packages / modules:

>>> 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>

En Python, il existe également des modules intégrés, tels que sys, qui sont écrits en C, mais je ne pense pas que vous vouliez les prendre en compte dans votre question.

Giulio Piancastelli
la source
9
Merci d'avoir mentionné explicitement que l'objet correspondant créé par Python est toujours de type module. Je suis en train d'écrire un débogueur et je craignais que mon débogueur n'ait pas raison de dire que mes packages étaient modules.
ArtOfWarfare le
8
@jolvi Les fichiers Python avec un nom de fichier contenant des tirets peuvent toujours être importés en tant que modules, mais pas avec l' importinstruction habituelle , car les tirets ne sont pas autorisés dans les identificateurs Python. Utilisez importlib.import_module()plutôt.
Giulio Piancastelli
2
@jolvi je ne le suis pas. Où dans mon commentaire lisez-vous cela? Je dis simplement que, si vous avez ou rencontrez un fichier Python avec des tirets dans son nom, vous pouvez toujours l'importer en tant que module. Je ne fais pas de déclaration sur la façon préférée de nommer un fichier Python. Je suis sûr que vous pouvez trouver cela ailleurs: il est généralement fortement conseillé d'éviter les tirets en faveur des traits de soulignement.
Giulio Piancastelli
3
Étant nouveau dans Python, les sous-packages ou modules n'étant pas disponibles par défaut lors de l'importation du package parent, c'est ce qui m'a fait trébucher. Y a-t-il une raison particulière à cela? Et existe-t-il un modèle commun pour rendre les sous-packages ou modules disponibles (via leur nom complet) lors de l'importation du package parent?
sschuberth
2
@sschuberth Importez simplement des sous-packages dans init .py d'un package parent.
Anna
33

Du glossaire Python :

Il est important de garder à l'esprit que tous les packages sont des modules, mais tous les modules ne sont pas des packages. Autrement dit, les packages ne sont qu'un type spécial de module. Plus précisément, tout module contenant un __path__attribut est considéré comme un package.

Les fichiers Python avec un tiret dans le nom, comme my-file.py, ne peuvent pas être importés avec une simple importinstruction. Au niveau du code, import my-fileest le même que celui import my - filequi déclenchera une exception. Ces fichiers sont mieux caractérisés comme des scripts alors que les fichiers importables sont des modules .

jolvi
la source
23

Tout d'abord, gardez à l'esprit que, dans sa définition précise, un module est un objet dans la mémoire d'un interpréteur Python, souvent créé en lisant un ou plusieurs fichiers à partir du disque. Bien que nous puissions appeler de manière informelle un fichier disque tel a/b/c.pyqu'un "module", il ne le devient en réalité que lorsqu'il est combiné avec des informations provenant de plusieurs autres sources (telles que sys.path) pour créer l'objet module.

(Note, par exemple, que les deux modules avec des noms différents peuvent être chargés à partir du même fichier, en fonction sys.pathet d' autres paramètres est exactement ce qui se passe avec. python -m my.moduleSuivi d'un import my.moduleà l'interprète, il y aura deux objets de module, __main__et my.module, à la fois créé du même fichier sur le disque,. my/module.py)

Un package est un module qui peut avoir des sous-modules (y compris des sous-packages). Tous les modules ne peuvent pas le faire. Par exemple, créez une petite hiérarchie de modules:

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

Assurez-vous qu'il n'y a pas d'autres fichiers sous a. Démarrez un interpréteur Python 3.4 ou version ultérieure (par exemple, avec python3 -i) et examinez les résultats des instructions suivantes:

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'>

Les modules aet a.bsont des packages (en fait, un certain type de package appelé «package d'espace de noms», bien que nous ne nous en préoccupions pas ici). Cependant, le module a.b.cn'est pas un package. Nous pouvons le démontrer en ajoutant un autre fichier a/b.pyà la structure de répertoires ci-dessus et en démarrant un nouvel interpréteur:

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 garantit que tous les modules parents sont chargés avant le chargement d'un module enfant. Au-dessus, il trouve qu'il a/s'agit d'un répertoire, et crée donc un package d'espace de noms a, et c'est a/b.pyun fichier source Python qu'il charge et utilise pour créer un module (non-package) a.b. À ce stade, vous ne pouvez pas avoir de module a.b.ccar il a.bne s'agit pas d'un package et ne pouvez donc pas avoir de sous-modules.

Vous pouvez également voir ici que le module de package aa un __path__attribut (les packages doivent en avoir) mais pas le module non-package a.b.

cjs
la source
1
Si vous ne l'avez pas déjà fait, revenez en arrière et étudiez les exemples de cette réponse.
Donal Lafferty
2

Une réponse tardive, encore une autre définition:

Un package est représenté par une entité supérieure importée qui peut être soit un module autonome, soit le __init__.pymodule spécial en tant qu'entité supérieure d'un ensemble de modules dans une structure de sous-répertoires.

Donc physiquement, un package est une unité de distribution, qui fournit un ou plusieurs modules.

acue
la source
1
Je pense qu'il y a deux définitions de paquet en Python et elles sont distinctes. Votre réponse semble les combiner ensemble. À strictement parler, un package python est un répertoire avec un __init__.pymodule à l'intérieur, mais si vous parlez d'unités de distribution (généralement via PyPI), il s'agit d'un autre type de package entièrement (généralement défini par l'existence de setup.py). Je trouve ces deux utilisations du terme packagedéroutantes, et j'ai parlé à certains débutants en Python qui le trouvent complètement déroutant.
davidA
@davidA, Ce n'est pas seulement ce que vous ressentez. Il a été codifié: packaging.python.org/glossary/#term-distribution-package (Merci aussi pour la clarification!)
Lorem Ipsum